void Vectorizer::setLevel(const TXshSimpleLevelP &level)
{
	m_level = level;

	//Creo il livello pli
	TXshSimpleLevel *sl = m_level.getPointer();
	if (!sl)
		return;

	int rowCount = sl->getFrameCount();
	if (rowCount <= 0 || sl->isEmpty())
		return;

	TXshLevel *xl;
	ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();

	// Build the new level name
	wstring levelName = sl->getName() + L"v";
	{
		std::auto_ptr<NameBuilder> nameBuilder(NameBuilder::getBuilder(levelName));

		for (;;) {
			levelName = nameBuilder->getNext();
			if (scene->getLevelSet()->getLevel(levelName) == 0)
				break;
		}
	}

	TFilePath dstPath = sl->getPath().withName(levelName).withType("pli");
	dstPath = scene->decodeFilePath(dstPath);

	bool overWrite = false;
	if (TSystem::doesExistFileOrLevel(dstPath)) {
		m_dialogShown = true;

		std::wstring name = m_dialog->execute(scene, dstPath, true);
		if (m_dialog->cancelPressed())
			return;

		switch (m_dialog->getChoice()) {
		case OverwriteDialog::KEEP_OLD: {
			xl = scene->getLevelSet()->getLevel(levelName);
			if (!xl)
				xl = scene->loadLevel(dstPath);

			m_vLevel = xl->getSimpleLevel();
			return;
		}

			CASE OverwriteDialog::OVERWRITE : overWrite = true;

		DEFAULT:
			levelName = name;
		}
	}

	xl = scene->createNewLevel(PLI_XSHLEVEL, levelName);

	TXshSimpleLevel *vl = xl->getSimpleLevel();
	assert(vl);

	if (overWrite) {
		vl->setPath(scene->codeFilePath(dstPath));
		vl->setName(levelName);
	}

	TPalette *palette = 0;
	if (sl->getType() == TZP_XSHLEVEL)
		palette = sl->getPalette();

	palette = palette ? palette->clone() : new TPalette;

	palette->setPaletteName(vl->getName());
	vl->setPalette(palette);

	m_vLevel = vl;
}
int Vectorizer::doVectorize()
{
	struct {
		Vectorizer *m_this;

		CenterlineConfiguration m_cConf;
		NewOutlineConfiguration m_oConf;

		void updateConfig(double weight)
		{
			if (m_this->m_params.m_isOutline)
				m_oConf = m_this->m_params.getOutlineConfiguration(weight);
			else
				m_cConf = m_this->m_params.getCenterlineConfiguration(weight);
		}

	} locals = {this};

	VectorizerConfiguration &configuration = m_params.m_isOutline ? static_cast<VectorizerConfiguration &>(locals.m_oConf) : static_cast<VectorizerConfiguration &>(locals.m_cConf);

	if (!m_vLevel)
		return 0;

	if (m_dialog->getChoice() == OverwriteDialog::KEEP_OLD && m_dialogShown)
		return m_fids.size();

	TXshSimpleLevel *sl = m_level.getPointer();
	if (!sl)
		return 0;

	int rowCount = sl->getFrameCount();
	if (rowCount <= 0 || sl->isEmpty())
		return 0;

	double frameRange[2] = {static_cast<double>(m_fids.front().getNumber()) - 1, static_cast<double>(m_fids.back().getNumber()) - 1};

	int count = 0;

	std::vector<TFrameId>::const_iterator ft, fEnd = m_fids.end();
	for (ft = m_fids.begin(); ft != fEnd; ++ft) {
		// Retrieve the image to be vectorized
		TImageP img;
		if (sl->getType() == OVL_XSHLEVEL ||
			sl->getType() == TZP_XSHLEVEL ||
			sl->getType() == TZI_XSHLEVEL)
			img = sl->getFullsampledFrame(*ft, ImageManager::dontPutInCache);

		if (!img)
			continue;

		// Build image-toonz coordinate transformation
		TAffine dpiAff = getDpiAffine(sl, *ft, true);
		double factor = norm(dpiAff * TPointD(1, 0));

		TPointD center;
		if (TToonzImageP ti = img)
			center = ti->getRaster()->getCenterD();
		else if (TRasterImageP ri = img)
			center = ri->getRaster()->getCenterD();

		// Build vectorizer configuration
		double weight = (ft->getNumber() - 1 - frameRange[0]) / tmax(frameRange[1] - frameRange[0], 1.0);
		weight = tcrop(weight, 0.0, 1.0);

		locals.updateConfig(weight); // TEMPORARY

		configuration.m_affine = dpiAff * TTranslation(-center);
		configuration.m_thickScale = factor;

		// Build vectorization label to be displayed
		QString labelName = QString::fromStdWString(sl->getShortName());
		labelName.push_back(' ');
		labelName.append(QString::fromStdString(ft->expand(TFrameId::NO_PAD)));

		emit frameName(labelName);

		// Perform vectorization
		if (TVectorImageP vi = doVectorize(img, m_vLevel->getPalette(), configuration)) {
			TFrameId fid = *ft;

			if (fid.getNumber() < 0)
				fid = TFrameId(1, ft->getLetter());

			m_vLevel->setFrame(fid, vi);
			vi->setPalette(m_vLevel->getPalette());

			emit frameDone(++count);
		}

		// Stop if canceled
		if (m_isCanceled)
			break;
	}

	m_dialogShown = false;

	return count;
}
示例#3
0
TImage *TTool::touchImage() {
  if (!m_application) return 0;

  m_cellsData.clear();

  m_isLevelCreated  = false;
  m_isFrameCreated  = false;
  Preferences *pref = Preferences::instance();

  bool isAutoCreateEnabled   = pref->isAutoCreateEnabled();
  bool animationSheetEnabled = pref->isAnimationSheetEnabled();
  bool isAutoStretchEnabled  = pref->isAutoStretchEnabled();

  TFrameHandle *currentFrame    = m_application->getCurrentFrame();
  TXshLevelHandle *currentLevel = m_application->getCurrentLevel();

  if (currentFrame->isEditingLevel()) {
    // Editing level

    // no level => return 0
    TXshLevel *xl = currentLevel->getLevel();
    if (!xl) return 0;
    TXshSimpleLevel *sl = xl->getSimpleLevel();
    if (!sl || sl->isEmpty()) return 0;

    TFrameId fid = currentFrame->getFid();
    TImageP img  = sl->getFrame(fid, true);
    if (!img) {
      // no drawing found
      if (sl->isSubsequence() || sl->isReadOnly() || !isAutoCreateEnabled)
        return 0;

      // create a new drawing
      img = sl->createEmptyFrame();
      sl->setFrame(fid, img);
      currentLevel->notifyLevelChange();
      m_isFrameCreated = true;
    }
    return img.getPointer();
  } else {
    // editing xsheet
    if (m_application->getCurrentObject()->isSpline()) return 0;

    TSceneHandle *currentScene = m_application->getCurrentScene();
    ToonzScene *scene          = currentScene->getScene();
    int row                    = currentFrame->getFrame();
    int col = m_application->getCurrentColumn()->getColumnIndex();
    if (col < 0) return 0;

    TXsheetHandle *currentXsheet = m_application->getCurrentXsheet();
    TXsheet *xsh                 = currentXsheet->getXsheet();
    if (!xsh) return 0;

    TXshCell cell       = xsh->getCell(row, col);
    TXshSimpleLevel *sl = cell.getSimpleLevel();

    if (sl != 0) {
      // current cell is not empty
      if (isAutoCreateEnabled && animationSheetEnabled && row > 0 &&
          xsh->getCell(row - 1, col) == xsh->getCell(row, col)) {
        // animationSheet is enabled and the current cell is a "hold". We must
        // create a new drawing.
        // measure the hold length (starting from the current row) : r0-r1
        int r0 = row, r1 = row;
        if (isAutoStretchEnabled)
          while (xsh->getCell(r1 + 1, col) == cell) r1++;
        // find the proper frameid (possibly addisng suffix, in order to avoid a
        // fid already used)
        TFrameId fid = getNewFrameId(sl, row);
        // create the new drawing
        TImageP img      = sl->createEmptyFrame();
        m_isFrameCreated = true;
        // insert the drawing in the level
        sl->setFrame(fid, img);
        // update the cell
        cell = TXshCell(sl, fid);
        // update the xsheet (change the current cell and possibly all the
        // following "hold")
        for (int r = r0; r <= r1; r++) xsh->setCell(r, col, cell);
        // notify
        currentXsheet->notifyXsheetChanged();
        currentScene->notifyCastChange();
        currentLevel->notifyLevelChange();
        m_cellsData.push_back(r0);
        m_cellsData.push_back(r1);
        m_cellsData.push_back(0);
      }
      // we've found the image. return it.
      return cell.getImage(true).getPointer();
    }

    // current cell is empty.
    if (!isAutoCreateEnabled) return 0;

    // get the column range
    int r0, r1;
    xsh->getCellRange(col, r0, r1);

    if (animationSheetEnabled && r0 <= r1) {
      // animation sheet enabled and not empty column. We must create a new
      // drawing in the column level and possibly add "holds"

      // find the last not-empty cell before the current one (a) and the first
      // after (b)
      int a = row - 1, b = row + 1;
      while (a >= r0 && xsh->getCell(a, col).isEmpty()) a--;
      while (b <= r1 && xsh->getCell(b, col).isEmpty()) b++;

      // find the level we must attach to
      if (a >= r0) {
        // there is a not-emtpy cell before the current one
        sl = xsh->getCell(a, col).getSimpleLevel();
      } else if (b <= r1) {
        sl = xsh->getCell(b, col).getSimpleLevel();
      }
      if (sl) {
        // note: sl should be always !=0 (the column is not empty)
        // if - for some reason - it is ==0 then we skip to the standard (i.e.
        // !animationSheetEnabled) beahviour

        // create the drawing
        // find the proper frameid (possibly addisng suffix, in order to avoid a
        // fid already used)
        TFrameId fid = getNewFrameId(sl, row);
        // create the new drawing
        TImageP img      = sl->createEmptyFrame();
        m_isFrameCreated = true;
        // insert the drawing in the level
        sl->setFrame(fid, img);
        // update the cell
        cell = TXshCell(sl, fid);
        xsh->setCell(row, col, cell);

        // create holds
        if (!isAutoStretchEnabled) {
          m_cellsData.push_back(row);
          m_cellsData.push_back(row);
          m_cellsData.push_back(2);  // vuoto => nuovo
        } else {
          if (a >= r0) {
            // create a hold before : [a+1, row-1]
            TXshCell aCell = xsh->getCell(a, col);
            for (int i = a + 1; i < row; i++) xsh->setCell(i, col, aCell);
            m_cellsData.push_back(a + 1);
            m_cellsData.push_back(row - 1);
            m_cellsData.push_back(1);  // vuoto => vecchio

            if (b <= r1 && xsh->getCell(b, col).getSimpleLevel() == sl) {
              // create also a hold after
              for (int i = row + 1; i < b; i++) xsh->setCell(i, col, cell);
              m_cellsData.push_back(row);
              m_cellsData.push_back(b - 1);
              m_cellsData.push_back(2);  // vuoto => nuovo
            } else {
              m_cellsData.push_back(row);
              m_cellsData.push_back(row);
              m_cellsData.push_back(2);  // vuoto => nuovo
            }
          } else if (b <= r1) {
            // create a hold after
            for (int i = row + 1; i < b; i++) xsh->setCell(i, col, cell);
            m_cellsData.push_back(row);
            m_cellsData.push_back(b - 1);
            m_cellsData.push_back(2);  // vuoto => nuovo
          }
        }
      }
      // notify & return
      currentXsheet->notifyXsheetChanged();
      currentScene->notifyCastChange();
      currentLevel->notifyLevelChange();
      return cell.getImage(true).getPointer();
    }

    if (row > 0 && xsh->getCell(row - 1, col).getSimpleLevel() != 0 &&
        !animationSheetEnabled) {
      sl = xsh->getCell(row - 1, col).getSimpleLevel();
      if (sl->getType() != OVL_XSHLEVEL ||
          sl->getPath().getFrame() != TFrameId::NO_FRAME) {
        // la cella precedente contiene un drawing di un livello. animationSheet
        // e' disabilitato
        // creo un nuovo frame
        currentLevel->setLevel(sl);
        if (sl->isSubsequence() || sl->isReadOnly()) return 0;
        TFrameId fid     = sl->index2fid(sl->getFrameCount());
        TImageP img      = sl->createEmptyFrame();
        m_isFrameCreated = true;
        sl->setFrame(fid, img);
        cell = TXshCell(sl, fid);
        xsh->setCell(row, col, cell);
        currentXsheet->notifyXsheetChanged();
        currentScene->notifyCastChange();
        currentLevel->notifyLevelChange();
        return img.getPointer();
      }
    }

    // animation sheet disabled or empty column. autoCreate is enabled: we must
    // create a new level
    int levelType    = pref->getDefLevelType();
    TXshLevel *xl    = scene->createNewLevel(levelType);
    sl               = xl->getSimpleLevel();
    m_isLevelCreated = true;

    // create the drawing
    TFrameId fid = animationSheetEnabled ? getNewFrameId(sl, row) : TFrameId(1);
    TImageP img  = sl->createEmptyFrame();
    m_isFrameCreated = true;
    sl->setFrame(fid, img);
    cell = TXshCell(sl, fid);
    xsh->setCell(row, col, cell);
    if (animationSheetEnabled) {
      m_cellsData.push_back(row);
      m_cellsData.push_back(row);
      m_cellsData.push_back(2);  // vuoto => nuovo
    }

    currentXsheet->notifyXsheetChanged();
    currentScene->notifyCastChange();
    currentLevel->notifyLevelChange();
    return img.getPointer();
  }
}