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;
}