Blame synfig-studio/src/synfigapp/vectorizer/centerlinecolors.cpp

Ankit Kumar Dwivedi 7dd184
/* === S Y N F I G ========================================================= */
Ankit Kumar Dwivedi 7dd184
/*!	\file centerlinecolors.cpp
Ankit Kumar Dwivedi 7dd184
**	\brief centerlinecolors File
Ankit Kumar Dwivedi 7dd184
**
Ankit Kumar Dwivedi 7dd184
**	$Id$
Ankit Kumar Dwivedi 7dd184
**
Ankit Kumar Dwivedi 7dd184
**	\legal
Ankit Kumar Dwivedi 7dd184
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
Ankit Kumar Dwivedi 7dd184
**
Ankit Kumar Dwivedi 7dd184
**	This package is free software; you can redistribute it and/or
Ankit Kumar Dwivedi 7dd184
**	modify it under the terms of the GNU General Public License as
Ankit Kumar Dwivedi 7dd184
**	published by the Free Software Foundation; either version 2 of
Ankit Kumar Dwivedi 7dd184
**	the License, or (at your option) any later version.
Ankit Kumar Dwivedi 7dd184
**
Ankit Kumar Dwivedi 7dd184
**	This package is distributed in the hope that it will be useful,
Ankit Kumar Dwivedi 7dd184
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Ankit Kumar Dwivedi 7dd184
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Ankit Kumar Dwivedi 7dd184
**	General Public License for more details.
Ankit Kumar Dwivedi 7dd184
**	\endlegal
Ankit Kumar Dwivedi 7dd184
*/
Ankit Kumar Dwivedi 7dd184
/* ========================================================================= */
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
/* === H E A D E R S ======================================================= */
Ankit Kumar Dwivedi a195e8
#include "polygonizerclasses.h"
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 121288
#include <synfig surface.h=""></synfig>
Ankit Kumar Dwivedi 121288
#include <synfig rendering="" software="" surfacesw.h=""></synfig>
Ankit Kumar Dwivedi 121288
#include <math.h></math.h>
Ankit Kumar Dwivedi 121288
#include <etl handle=""></etl>
Ankit Kumar Dwivedi 121288
#include <synfig layer_bitmap.h="" layers=""></synfig>
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
/* === U S I N G =========================================================== */
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
using namespace std;
Ankit Kumar Dwivedi 7dd184
using namespace etl;
Ankit Kumar Dwivedi 7dd184
using namespace studio;
Ankit Kumar Dwivedi a195e8
using namespace synfig;
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
/* === M A C R O S ========================================================= */
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
/* === G L O B A L S ======================================================= */
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
/* === P R O C E D U R E S ================================================= */
Ankit Kumar Dwivedi a195e8
a4bbdd
synfig::Color pixelToColor(const Surface &rsurface, int x, int y, const Gamma &gamma)
Ankit Kumar Dwivedi a195e8
{
a4bbdd
	const int Y = rsurface.get_h() - y - 1;
a4bbdd
	return gamma.apply(rsurface[Y][x]);
Ankit Kumar Dwivedi a195e8
}
Ankit Kumar Dwivedi a195e8
a4bbdd
bool checkPixelThreshold(const Surface &rsurface, int x, int y, int threshold)
Ankit Kumar Dwivedi a195e8
{
a4bbdd
	const int Y = rsurface.get_h() - y -1; 
a4bbdd
	const Color color = rsurface[Y][x];
a4bbdd
	int r = 255.99*color.get_r();
a4bbdd
	int g = 255.99*color.get_g();
a4bbdd
	int b = 255.99*color.get_b();
a4bbdd
	int a = 255.99*color.get_a();
a4bbdd
	return std::max(r,std::max(g,b)) < threshold * (a / 255.0);
Ankit Kumar Dwivedi a195e8
}
Ankit Kumar Dwivedi a195e8
Ankit Kumar Dwivedi 4792ed
//------------------------------------------------------------------------
a4bbdd
static synfig::Point3 firstInkChangePosition(
a4bbdd
	const Surface &ras,
a4bbdd
	const synfig::Point3 &start,
a4bbdd
	const synfig::Point3 &end,
a4bbdd
	int threshold,
a4bbdd
	const Gamma &gamma )
Ankit Kumar Dwivedi 121288
{
Ankit Kumar Dwivedi 121288
  double dist = (end - start).mag();
Ankit Kumar Dwivedi 121288
Ankit Kumar Dwivedi a195e8
  int sampleMax = ceil_to_int(dist), sampleCount = sampleMax + 1;
Ankit Kumar Dwivedi 121288
  double sampleMaxD = double(sampleMax);
Ankit Kumar Dwivedi 121288
Ankit Kumar Dwivedi 121288
  // Get first ink color
Ankit Kumar Dwivedi a195e8
  int s;
Ankit Kumar Dwivedi a195e8
  synfig::Color color ;
Ankit Kumar Dwivedi 121288
Ankit Kumar Dwivedi a195e8
  for (s = 0; s != sampleCount; ++s) 
Ankit Kumar Dwivedi a195e8
  {
Ankit Kumar Dwivedi a195e8
    synfig::Point3 p  = start * (1 - s/sampleMaxD) +  end * (s/sampleMaxD);
Ankit Kumar Dwivedi a195e8
    // const TPixelCM32 &pix = pixel(*ras, p.x, p.y);
Ankit Kumar Dwivedi a195e8
    if (checkPixelThreshold(ras,p[0],p[1], threshold)) 
Ankit Kumar Dwivedi a195e8
    {
a4bbdd
      color = pixelToColor(ras, p[0], p[1], gamma);
Ankit Kumar Dwivedi 121288
      break;
Ankit Kumar Dwivedi 121288
    }
Ankit Kumar Dwivedi 121288
  }
Ankit Kumar Dwivedi 121288
Ankit Kumar Dwivedi 121288
  // Get second color
Ankit Kumar Dwivedi a195e8
  for (; s != sampleCount; ++s) 
Ankit Kumar Dwivedi a195e8
  {
Ankit Kumar Dwivedi a195e8
    synfig::Point3 p = start *(1 - s/sampleMaxD) +  end * (s/sampleMaxD);
Ankit Kumar Dwivedi a195e8
    // const TPixelCM32 &pix = pixel(*ras, p.x, p.y);
Ankit Kumar Dwivedi 121288
a4bbdd
    if (checkPixelThreshold(ras,p[0],p[1],threshold) && pixelToColor(ras, p[0], p[1], gamma) != color)
Ankit Kumar Dwivedi a195e8
     break;
Ankit Kumar Dwivedi 121288
  }
Ankit Kumar Dwivedi 121288
Ankit Kumar Dwivedi 121288
  // Return middle position between s-1 and s
Ankit Kumar Dwivedi 121288
  if (s < sampleCount)
Ankit Kumar Dwivedi a195e8
    return start * (1 - ((s - 0.5) / sampleMaxD)) + end * ((s - 0.5) / sampleMaxD);
Ankit Kumar Dwivedi 121288
Ankit Kumar Dwivedi a195e8
  return synfig::Point3::nan();
Ankit Kumar Dwivedi 121288
}
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
// Find color of input sequence. Will be copied to its equivalent stroke.
Ankit Kumar Dwivedi 4792ed
// Currently in use only on colormaps
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
// Summary: It is better to test the color to be assigned to the strokes
Ankit Kumar Dwivedi 4792ed
// to check
Ankit Kumar Dwivedi 4792ed
// sequences * before * convert them to TStroke (since you lose part
Ankit Kumar Dwivedi 4792ed
// of the original grip
Ankit Kumar Dwivedi 4792ed
// to the line). You specify a number of 'taste points' of the broken line
Ankit Kumar Dwivedi 4792ed
// equidistant from each other,
Ankit Kumar Dwivedi 4792ed
// on which the value of the corresponding pixel input is taken. If
Ankit Kumar Dwivedi 4792ed
// identifies a change
Ankit Kumar Dwivedi 4792ed
// of color, the sequence breaking procedure is launched: yes
Ankit Kumar Dwivedi 4792ed
// identifies the point
Ankit Kumar Dwivedi 4792ed
// of breaking, and the sequence s is blocked there; a new one is built
Ankit Kumar Dwivedi 4792ed
// sequence newSeq e
Ankit Kumar Dwivedi 4792ed
// sampleColor is re-launched (ras, newSeq, sOpposite). Sequences between two points
Ankit Kumar Dwivedi 4792ed
// of breaking up
Ankit Kumar Dwivedi 4792ed
// are inserted into the vector 'globals-> singleSequences'.
Ankit Kumar Dwivedi 4792ed
// In the case of circular sequences there is a small change: the first point of
Ankit Kumar Dwivedi 4792ed
// splitting
Ankit Kumar Dwivedi 4792ed
// * only redefines * the s-node, without introducing new sequences.
Ankit Kumar Dwivedi 4792ed
// The sequence sOpposite, 'inverse' of s, remains and becomes 'forward-oriented'
Ankit Kumar Dwivedi 4792ed
// after updating
Ankit Kumar Dwivedi 4792ed
// of the tail.
Ankit Kumar Dwivedi 4792ed
// Notice that the break nodes are entered with the signature
Ankit Kumar Dwivedi 4792ed
// 'SAMPLECOLOR_SIGN'.
Ankit Kumar Dwivedi 4792ed
// NOTE: The J-S 'upper' graph structure is not altered in here.
Ankit Kumar Dwivedi 4792ed
// Eventualm. to do outside.
Ankit Kumar Dwivedi 4792ed
a4bbdd
static void sampleColor(
a4bbdd
	const etl::handle<synfig::layer_bitmap> &ras,</synfig::layer_bitmap>
a4bbdd
	int threshold,
a4bbdd
	Sequence &seq,
a4bbdd
	Sequence &seqOpposite,
a4bbdd
	SequenceList &singleSequences,
a4bbdd
	const Gamma &gamma ) 
Ankit Kumar Dwivedi 121288
{
Ankit Kumar Dwivedi 4792ed
  SkeletonGraph *currGraph = seq.m_graphHolder;
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Calculate sequence parametrization
Ankit Kumar Dwivedi 4792ed
  std::vector<unsigned int=""> nodes;</unsigned>
Ankit Kumar Dwivedi 4792ed
  std::vector<double> params;</double>
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Meanwhile, ensure each point belong to ras. Otherwise, typically an error
Ankit Kumar Dwivedi a195e8
  // occured in the thinning process and it's better avoid sampling procedure. Only
Ankit Kumar Dwivedi 4792ed
  // exception, when
Ankit Kumar Dwivedi 121288
  // a point has x==rsurface.get_w() || y==rsurface.get_h(); that is accepted.
Ankit Kumar Dwivedi 32d730
  synfig::rendering::SurfaceResource::LockRead<synfig::rendering::surfacesw> lock( ras->rendering_surface ); </synfig::rendering::surfacesw>
Ankit Kumar Dwivedi 121288
	const Surface &rsurface = lock->get_surface(); 
Ankit Kumar Dwivedi 4792ed
  {
Ankit Kumar Dwivedi 4792ed
    const synfig::Point3 &headPos = *currGraph->getNode(seq.m_head);
Ankit Kumar Dwivedi 4792ed
    // get bounds rectangle with = 0,0,lx -1, ly-1
Ankit Kumar Dwivedi 121288
    if (headPos[0] < 0 || rsurface.get_w() < headPos[0] || headPos[1] < 0 || rsurface.get_h() < headPos[1])// check again and return
Ankit Kumar Dwivedi 4792ed
        return;
Ankit Kumar Dwivedi 32d730
    
Ankit Kumar Dwivedi 4792ed
  }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  unsigned int curr, currLink, next;
Ankit Kumar Dwivedi a195e8
  double meanThickness = currGraph->getNode(seq.m_head)->operator[](2);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  params.push_back(0);
Ankit Kumar Dwivedi 4792ed
  nodes.push_back(seq.m_head);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  for (curr = seq.m_head, currLink = seq.m_headLink;
Ankit Kumar Dwivedi 4792ed
       curr != seq.m_tail || params.size() == 1; seq.next(curr, currLink)) 
Ankit Kumar Dwivedi 4792ed
  {
Ankit Kumar Dwivedi 4792ed
    next = currGraph->getNode(curr).getLink(currLink).getNext();
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
    const synfig::Point3 &nextPos = *currGraph->getNode(next);
Ankit Kumar Dwivedi 121288
    if (nextPos[0] < 0 || rsurface.get_w() < nextPos[0] || nextPos[1] < 0 || rsurface.get_h() < nextPos[1]) 
Ankit Kumar Dwivedi 4792ed
    {
Ankit Kumar Dwivedi 32d730
      return;
Ankit Kumar Dwivedi 4792ed
    }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 32d730
    params.push_back(params.back() + (*currGraph->getNode(next) - *currGraph->getNode(curr)).mag());
Ankit Kumar Dwivedi 4792ed
    nodes.push_back(next);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 121288
    meanThickness += currGraph->getNode(next)->operator[](2);
Ankit Kumar Dwivedi 4792ed
  }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  meanThickness /= params.size();
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Exclude 0-length sequences
Ankit Kumar Dwivedi 32d730
  if (params.back() < 0.01) 
Ankit Kumar Dwivedi 32d730
  {
a4bbdd
    seq.m_color = pixelToColor(
a4bbdd
		rsurface,
a4bbdd
		currGraph->getNode(seq.m_head)->operator[](0),
a4bbdd
		currGraph->getNode(seq.m_head)->operator[](1),
a4bbdd
		gamma );
Ankit Kumar Dwivedi 4792ed
    return;
Ankit Kumar Dwivedi 4792ed
  }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Prepare sampling procedure
Ankit Kumar Dwivedi 4792ed
  int paramCount = params.size(), paramMax = paramCount - 1;
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 32d730
  int sampleMax = std::max(params.back() / std::max(meanThickness, 1.0),3.0),    // Number of color samples depends on
Ankit Kumar Dwivedi 4792ed
      sampleCount = sampleMax + 1;  // the ratio params.back() / meanThickness
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  std::vector<double> sampleParams(sampleCount);  // Sampling lengths</double>
Ankit Kumar Dwivedi 32d730
  std::vector<synfig::point> samplePoints(sampleCount);  // Image points for color sampling</synfig::point>
Ankit Kumar Dwivedi 32d730
  std::vector<int> sampleSegments(sampleCount);  // Sequence segment index for the above</int>
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Sample colors
Ankit Kumar Dwivedi 32d730
  for (int s = 0, j = 0; s != sampleCount; ++s) 
Ankit Kumar Dwivedi 32d730
  {
Ankit Kumar Dwivedi 4792ed
    double samplePar = params.back() * (s / double(sampleMax));
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 32d730
    while (j != paramMax && params[j + 1] < samplePar)  // params[j] < samplePar <= params[j+1]
Ankit Kumar Dwivedi 4792ed
      ++j;
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
    double t = (samplePar - params[j]) / (params[j + 1] - params[j]);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
    synfig::Point3 samplePoint(*currGraph->getNode(nodes[j]) * (1 - t) +
Ankit Kumar Dwivedi 4792ed
                          *currGraph->getNode(nodes[j + 1]) * t);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
    sampleParams[s] = samplePar;
Ankit Kumar Dwivedi 4792ed
    samplePoints[s] = synfig::Point(
Ankit Kumar Dwivedi 4792ed
        std::min(samplePoint[0],
Ankit Kumar Dwivedi 121288
                 double(rsurface.get_w() - 1)),  // This deals with sample points at
Ankit Kumar Dwivedi 4792ed
        std::min(samplePoint[1],
Ankit Kumar Dwivedi 121288
                 double(rsurface.get_h() - 1)));  // the top/right raster border
Ankit Kumar Dwivedi 4792ed
    sampleSegments[s] = j;
Ankit Kumar Dwivedi 4792ed
  }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // NOTE: Extremities of a sequence are considered unreliable: they typically
Ankit Kumar Dwivedi 4792ed
  // happen
Ankit Kumar Dwivedi 4792ed
  //       to be junction points shared between possibly different-colored
Ankit Kumar Dwivedi 4792ed
  //       strokes.
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Find first and last extremity-free sampled points
Ankit Kumar Dwivedi 4792ed
  synfig::Point3 first(*currGraph->getNode(seq.m_head));
Ankit Kumar Dwivedi 4792ed
  synfig::Point3 last(*currGraph->getNode(seq.m_tail));
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  int i, k;
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  for (i = 1;
Ankit Kumar Dwivedi 121288
       params.back() * i / double(sampleMax) <= first[2] && i < sampleCount; ++i)
Ankit Kumar Dwivedi 4792ed
    ;
Ankit Kumar Dwivedi 4792ed
  for (k = sampleMax - 1;
Ankit Kumar Dwivedi 121288
       params.back() * (sampleMax - k) / double(sampleMax) <= last[2] && k >= 0;
Ankit Kumar Dwivedi 4792ed
       --k)
Ankit Kumar Dwivedi 4792ed
    ;
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Give s the first sampled ink color found
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Initialize with a last-resort reasonable color - not just 0
a4bbdd
  seq.m_color = seqOpposite.m_color = pixelToColor(rsurface, samplePoints[0][0], samplePoints[0][1], gamma);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  int l;
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 121288
  for (l = i - 1; l >= 0; --l) 
Ankit Kumar Dwivedi 121288
  {
a4bbdd
    if (checkPixelThreshold(rsurface, samplePoints[l][0], samplePoints[l][1], threshold))
Ankit Kumar Dwivedi 121288
    {
a4bbdd
      seq.m_color = seqOpposite.m_color = pixelToColor(rsurface, samplePoints[l][0], samplePoints[l][1], gamma);
Ankit Kumar Dwivedi 4792ed
      break;
Ankit Kumar Dwivedi 4792ed
    }
Ankit Kumar Dwivedi 4792ed
  }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Then, look for the first reliable ink
Ankit Kumar Dwivedi 121288
  for (l = i; l <= k; ++l) 
Ankit Kumar Dwivedi 121288
  {
Ankit Kumar Dwivedi a195e8
    if (checkPixelThreshold(rsurface,samplePoints[l][0],samplePoints[l][1], threshold))
Ankit Kumar Dwivedi 121288
    {
a4bbdd
      seq.m_color = seqOpposite.m_color = pixelToColor(rsurface, samplePoints[l][0], samplePoints[l][1], gamma);
Ankit Kumar Dwivedi 4792ed
      break;
Ankit Kumar Dwivedi 4792ed
    }
Ankit Kumar Dwivedi 4792ed
  }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  if (i >= k) goto _getOut;  // No admissible segment found for splitting
Ankit Kumar Dwivedi 4792ed
                             // check.
Ankit Kumar Dwivedi 4792ed
  // Find color changes between sampled colors
Ankit Kumar Dwivedi 121288
  for (l = i; l < k; ++l) 
Ankit Kumar Dwivedi 121288
  {
Ankit Kumar Dwivedi 121288
    const int x1 = samplePoints[l + 1][0], y1 = samplePoints[l + 1][1],
Ankit Kumar Dwivedi 121288
              x2 = samplePoints[l + 2][0], y2 = samplePoints[l + 2][1];
Ankit Kumar Dwivedi 121288
    
Ankit Kumar Dwivedi 121288
    // const TPixelCM32
Ankit Kumar Dwivedi 121288
    //     &nextSample = ras->pixels(x1)[y1],
Ankit Kumar Dwivedi 121288
    //     &nextSample2 = ras->pixels(x2)[y2];  // l < k < sampleMax - so +2 is ok
Ankit Kumar Dwivedi 121288
a4bbdd
    if (checkPixelThreshold(rsurface, x1, y1, threshold) &&
a4bbdd
        pixelToColor(rsurface, x1, y1, gamma) != seq.m_color &&
a4bbdd
        checkPixelThreshold(rsurface, x2, y2, threshold) &&
a4bbdd
        pixelToColor(rsurface, x2, y2, gamma) == pixelToColor(rsurface, x1, y1, gamma))  // Ignore single-sample color changes
Ankit Kumar Dwivedi 4792ed
    {
Ankit Kumar Dwivedi 4792ed
      // Found a color change - apply splitting procedure
Ankit Kumar Dwivedi 4792ed
      // NOTE: The function RETURNS BEFORE THE FOR IS CONTINUED!
Ankit Kumar Dwivedi 4792ed
a4bbdd
      synfig::Color nextColor = pixelToColor(rsurface, x1, y1, gamma);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
      // Identify split segment
Ankit Kumar Dwivedi 4792ed
      int u;
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 121288
      for (u = sampleSegments[l]; u < sampleSegments[l + 1]; ++u) 
Ankit Kumar Dwivedi 121288
      {
Ankit Kumar Dwivedi 121288
        const int x = currGraph->getNode(nodes[u + 1])->operator[](0),
Ankit Kumar Dwivedi 121288
                  y = currGraph->getNode(nodes[u + 1])->operator[](1);
a4bbdd
        if (checkPixelThreshold(rsurface, x, y, threshold) && pixelToColor(rsurface, x, y, gamma) != seq.m_color)
Ankit Kumar Dwivedi 121288
         break;
Ankit Kumar Dwivedi 4792ed
      }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
      // Now u indicates the splitting segment. Search for splitting point by
Ankit Kumar Dwivedi 4792ed
      // binary subdivision.
Ankit Kumar Dwivedi 4792ed
      const synfig::Point3 &nodeStartPos = *currGraph->getNode(nodes[u]),
Ankit Kumar Dwivedi 121288
                           &nodeEndPos   = *currGraph->getNode(nodes[u + 1]);
Ankit Kumar Dwivedi 4792ed
a4bbdd
      synfig::Point3 splitPoint = firstInkChangePosition(rsurface, nodeStartPos, nodeEndPos, threshold, gamma);
Ankit Kumar Dwivedi a195e8
Ankit Kumar Dwivedi a195e8
      if (splitPoint == synfig::Point3::nan())
Ankit Kumar Dwivedi a195e8
        splitPoint = (nodeStartPos + nodeEndPos) * 0.5; 
Ankit Kumar Dwivedi a195e8
      // A color change was found, but could not be precisely located. Just take
Ankit Kumar Dwivedi a195e8
      // a reasonable representant. Insert a corresponding new node in basic graph structure.
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
      unsigned int splitNode = currGraph->newNode(splitPoint);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
      unsigned int nodesLink =
Ankit Kumar Dwivedi 4792ed
          currGraph->getNode(nodes[u]).linkOfNode(nodes[u + 1]);
Ankit Kumar Dwivedi 4792ed
      currGraph->insert(splitNode, nodes[u], nodesLink);
Ankit Kumar Dwivedi 4792ed
      *currGraph->node(splitNode).link(0) =
Ankit Kumar Dwivedi 4792ed
          *currGraph->getNode(nodes[u]).getLink(nodesLink);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
      nodesLink = currGraph->getNode(nodes[u + 1]).linkOfNode(nodes[u]);
Ankit Kumar Dwivedi 4792ed
      currGraph->insert(splitNode, nodes[u + 1], nodesLink);
Ankit Kumar Dwivedi 4792ed
      *currGraph->node(splitNode).link(1) =
Ankit Kumar Dwivedi 4792ed
          *currGraph->getNode(nodes[u + 1]).getLink(nodesLink);
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi a195e8
      currGraph->node(splitNode).setAttribute(SAMPLECOLOR_SIGN);  // Sign all split-inserted nodes
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
      if (seq.m_head == seq.m_tail &&
Ankit Kumar Dwivedi 4792ed
          currGraph->getNode(seq.m_head).getLinksCount() == 2 &&
Ankit Kumar Dwivedi a195e8
          !currGraph->getNode(seq.m_head).hasAttribute(SAMPLECOLOR_SIGN)) 
Ankit Kumar Dwivedi a195e8
      {
Ankit Kumar Dwivedi 4792ed
        // Circular case: we update s to splitNode and relaunch this very
Ankit Kumar Dwivedi 4792ed
        // procedure on it.
Ankit Kumar Dwivedi 4792ed
        seq.m_head = seq.m_tail = splitNode;
a4bbdd
        sampleColor(ras, threshold, seq, seqOpposite, singleSequences, gamma);
Ankit Kumar Dwivedi a195e8
      } 
Ankit Kumar Dwivedi a195e8
      else 
Ankit Kumar Dwivedi a195e8
      {
Ankit Kumar Dwivedi 4792ed
        // Update upper (Joint-Sequence) graph data
Ankit Kumar Dwivedi 4792ed
        Sequence newSeq;
Ankit Kumar Dwivedi 4792ed
        newSeq.m_graphHolder = currGraph;
Ankit Kumar Dwivedi 4792ed
        newSeq.m_head        = splitNode;
Ankit Kumar Dwivedi 4792ed
        newSeq.m_headLink    = 0;
Ankit Kumar Dwivedi 4792ed
        newSeq.m_tail        = seq.m_tail;
Ankit Kumar Dwivedi 4792ed
        newSeq.m_tailLink    = seq.m_tailLink;
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
        seq.m_tail     = splitNode;
Ankit Kumar Dwivedi 4792ed
        seq.m_tailLink = 1;  // (link from splitNode to nodes[u] inserted for
Ankit Kumar Dwivedi 4792ed
                             // second by 'insert')
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi a195e8
        seqOpposite.m_graphHolder = seq.m_graphHolder;  // Inform that a split was found
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
        // NOTE: access on s terminates at newSeq's push_back, due to possible
Ankit Kumar Dwivedi 4792ed
        // reallocation of globals->singleSequences
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
        if ((!(seq.m_head == newSeq.m_tail &&
Ankit Kumar Dwivedi 4792ed
               currGraph->getNode(seq.m_head).getLinksCount() == 2)) &&
Ankit Kumar Dwivedi 4792ed
            currGraph->getNode(seq.m_head).hasAttribute(SAMPLECOLOR_SIGN))
Ankit Kumar Dwivedi 4792ed
          singleSequences.push_back(seq);
Ankit Kumar Dwivedi 4792ed
a4bbdd
        sampleColor(ras, threshold, newSeq, seqOpposite, singleSequences, gamma);
Ankit Kumar Dwivedi 4792ed
      }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
      return;
Ankit Kumar Dwivedi 4792ed
    }
Ankit Kumar Dwivedi 4792ed
  }
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
_getOut:
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 4792ed
  // Color changes not found (and therefore no newSeq got pushed back); if a
Ankit Kumar Dwivedi 4792ed
  // split happened, update sOpposite.
Ankit Kumar Dwivedi 4792ed
  if (currGraph->getNode(seq.m_head).hasAttribute(SAMPLECOLOR_SIGN)) {
Ankit Kumar Dwivedi 4792ed
    seqOpposite.m_color    = seq.m_color;
Ankit Kumar Dwivedi 4792ed
    seqOpposite.m_head     = seq.m_tail;
Ankit Kumar Dwivedi 4792ed
    seqOpposite.m_headLink = seq.m_tailLink;
Ankit Kumar Dwivedi 4792ed
    seqOpposite.m_tail     = seq.m_head;
Ankit Kumar Dwivedi 4792ed
    seqOpposite.m_tailLink = seq.m_headLink;
Ankit Kumar Dwivedi 4792ed
  }
Ankit Kumar Dwivedi 4792ed
}
Ankit Kumar Dwivedi 4792ed
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
/* === M E T H O D S ======================================================= */
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
/* === E N T R Y P O I N T ================================================= */
Ankit Kumar Dwivedi 7dd184
a4bbdd
void studio::calculateSequenceColors(const etl::handle<synfig::layer_bitmap> &ras, VectorizerCoreGlobals &g, const Gamma &gamma)</synfig::layer_bitmap>
Ankit Kumar Dwivedi 7dd184
{
Ankit Kumar Dwivedi 7dd184
  int threshold                           = g.currConfig->m_threshold;
Ankit Kumar Dwivedi 7dd184
  SequenceList &singleSequences           = g.singleSequences;
Ankit Kumar Dwivedi 7dd184
  JointSequenceGraphList &organizedGraphs = g.organizedGraphs;
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
  unsigned int i, j, k;
Ankit Kumar Dwivedi 7dd184
  int l;
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 32d730
  if (ras && g.currConfig->m_maxThickness > 0.0) 
Ankit Kumar Dwivedi 7dd184
  {
Ankit Kumar Dwivedi 7dd184
    // singleSequence is traversed back-to-front because new, possibly splitted
Ankit Kumar Dwivedi 7dd184
    // sequences
Ankit Kumar Dwivedi 7dd184
    // are inserted at back - and don't have to be re-sampled.
Ankit Kumar Dwivedi 7dd184
    for (l = singleSequences.size() - 1; l >= 0; --l) 
Ankit Kumar Dwivedi 7dd184
    {
Ankit Kumar Dwivedi 7dd184
      Sequence rear;
a4bbdd
      sampleColor(ras, threshold, singleSequences[l], rear, singleSequences, gamma);
Ankit Kumar Dwivedi 7dd184
      // If rear is built, a split occurred and the rear of this
Ankit Kumar Dwivedi 7dd184
      // single sequence has to be pushed back.
Ankit Kumar Dwivedi 7dd184
      if (rear.m_graphHolder) singleSequences.push_back(rear);
Ankit Kumar Dwivedi 7dd184
    }
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
    for (i = 0; i < organizedGraphs.size(); ++i)
Ankit Kumar Dwivedi 7dd184
    {
Ankit Kumar Dwivedi 7dd184
        for (j = 0; j < organizedGraphs[i].getNodesCount(); ++j)
Ankit Kumar Dwivedi 7dd184
        {
Ankit Kumar Dwivedi 32d730
          if (!organizedGraphs[i].getNode(j).hasAttribute(JointSequenceGraph::ELIMINATED))
Ankit Kumar Dwivedi 32d730
          {
Ankit Kumar Dwivedi 32d730
              for (k = 0; k < organizedGraphs[i].getNode(j).getLinksCount(); ++k) 
Ankit Kumar Dwivedi 32d730
              {
Ankit Kumar Dwivedi 32d730
                  Sequence &s = *organizedGraphs[i].node(j).link(k);
Ankit Kumar Dwivedi 32d730
                  if (s.isForward() && !s.m_graphHolder->getNode(s.m_tail).hasAttribute(SAMPLECOLOR_SIGN))
Ankit Kumar Dwivedi 32d730
                  {
Ankit Kumar Dwivedi 7dd184
                    unsigned int next = organizedGraphs[i].node(j).link(k).getNext();
Ankit Kumar Dwivedi 7dd184
                    unsigned int nextLink = organizedGraphs[i].tailLinkOf(j, k);
Ankit Kumar Dwivedi 7dd184
                    Sequence &sOpposite = *organizedGraphs[i].node(next).link(nextLink);
a4bbdd
                    sampleColor(ras, threshold, s, sOpposite, singleSequences, gamma);
Ankit Kumar Dwivedi 32d730
                  }
Ankit Kumar Dwivedi 32d730
              }
Ankit Kumar Dwivedi 32d730
          }  
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
        }
Ankit Kumar Dwivedi 7dd184
    }
Ankit Kumar Dwivedi 7dd184
      
Ankit Kumar Dwivedi 7dd184
  }
Ankit Kumar Dwivedi 7dd184
}
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi 7dd184
//==========================================================================
Ankit Kumar Dwivedi f0aee8
//==========================================================================
Ankit Kumar Dwivedi f0aee8
Ankit Kumar Dwivedi f0aee8
// Take samples of image colors to associate each stroke to its corresponding
Ankit Kumar Dwivedi f0aee8
// palette color. Currently working on colormaps, closest-to-black strokes
Ankit Kumar Dwivedi f0aee8
// otherwise.
Ankit Kumar Dwivedi d3f8e5
/*
Ankit Kumar Dwivedi f0aee8
void applyStrokeColors(std::vector<tstroke *=""> &strokes, const TRasterP &ras,</tstroke>
Ankit Kumar Dwivedi f0aee8
                       TPalette *palette, VectorizerCoreGlobals &g) {
Ankit Kumar Dwivedi f0aee8
  JointSequenceGraphList &organizedGraphs = g.organizedGraphs;
Ankit Kumar Dwivedi f0aee8
  SequenceList &singleSequences           = g.singleSequences;
Ankit Kumar Dwivedi f0aee8
Ankit Kumar Dwivedi f0aee8
  TRasterCM32P cm = ras;
Ankit Kumar Dwivedi f0aee8
  unsigned int i, j, k, n;
Ankit Kumar Dwivedi f0aee8
Ankit Kumar Dwivedi f0aee8
  if (cm && g.currConfig->m_maxThickness > 0.0) 
Ankit Kumar Dwivedi f0aee8
  {
Ankit Kumar Dwivedi f0aee8
    applyStrokeIndices(&g);
Ankit Kumar Dwivedi f0aee8
Ankit Kumar Dwivedi f0aee8
    // Treat single sequences before, like conversionToStrokes(..)
Ankit Kumar Dwivedi f0aee8
    for (i = 0; i < singleSequences.size(); ++i)
Ankit Kumar Dwivedi f0aee8
      strokes[i]->setStyle(singleSequences[i].m_color);
Ankit Kumar Dwivedi f0aee8
Ankit Kumar Dwivedi f0aee8
    // Then, treat remaining graph-strokes
Ankit Kumar Dwivedi f0aee8
    n = i;
Ankit Kumar Dwivedi f0aee8
Ankit Kumar Dwivedi f0aee8
    for (i = 0; i < organizedGraphs.size(); ++i)
Ankit Kumar Dwivedi f0aee8
      for (j = 0; j < organizedGraphs[i].getNodesCount(); ++j)
Ankit Kumar Dwivedi f0aee8
        if (!organizedGraphs[i].getNode(j).hasAttribute(
Ankit Kumar Dwivedi f0aee8
                JointSequenceGraph::ELIMINATED))  // due to junction recovery
Ankit Kumar Dwivedi f0aee8
          for (k = 0; k < organizedGraphs[i].getNode(j).getLinksCount(); ++k) {
Ankit Kumar Dwivedi f0aee8
            Sequence &s = *organizedGraphs[i].node(j).link(k);
Ankit Kumar Dwivedi f0aee8
            if (s.isForward()) {
Ankit Kumar Dwivedi f0aee8
              // vi->getStroke(n)->setStyle(s.m_color);
Ankit Kumar Dwivedi f0aee8
              strokes[n]->setStyle(s.m_color);
Ankit Kumar Dwivedi f0aee8
              ++n;
Ankit Kumar Dwivedi f0aee8
            }
Ankit Kumar Dwivedi f0aee8
          }
Ankit Kumar Dwivedi f0aee8
Ankit Kumar Dwivedi f0aee8
    // Order vector image according to actual color-coverings at junctions.
Ankit Kumar Dwivedi f0aee8
    orderColoredStrokes(organizedGraphs, strokes, cm, palette);
Ankit Kumar Dwivedi f0aee8
  }
Ankit Kumar Dwivedi f0aee8
  else
Ankit Kumar Dwivedi f0aee8
  {
Ankit Kumar Dwivedi f0aee8
    // Choose closest-to-black palette color
Ankit Kumar Dwivedi f0aee8
    int blackStyleId = palette->getClosestStyle(TPixel32::Black);
Ankit Kumar Dwivedi f0aee8
Ankit Kumar Dwivedi f0aee8
    unsigned int i;
Ankit Kumar Dwivedi f0aee8
    for (i = 0; i < strokes.size(); ++i) strokes[i]->setStyle(blackStyleId);
Ankit Kumar Dwivedi f0aee8
  }
Ankit Kumar Dwivedi f0aee8
}
Ankit Kumar Dwivedi 7dd184
Ankit Kumar Dwivedi d3f8e5
*/
Ankit Kumar Dwivedi 7dd184