Example #1
0
void inkFill(const TRasterCM32P &r, const TPoint &pin, int ink, int searchRay,
			 TTileSaverCM32 *saver, TRect *insideRect)
{
	r->lock();
	TPixelCM32 *pixels = (TPixelCM32 *)r->getRawData();
	int oldInk;
	TPoint p = pin;

	if ((pixels + p.y * r->getWrap() + p.x)->isPurePaint() && (searchRay == 0 ||
															   (p = nearestInk(r, p, searchRay)) == TPoint(-1, -1))) {
		r->unlock();
		return;
	}
	TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);

	if (pix->getInk() == ink) {
		r->unlock();
		return;
	}

	oldInk = pix->getInk();

	std::stack<TPoint> seeds;
	seeds.push(p);

	while (!seeds.empty()) {
		p = seeds.top();
		seeds.pop();
		if (!r->getBounds().contains(p))
			continue;
		if (insideRect && !insideRect->contains(p))
			continue;

		TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);
		if (pix->isPurePaint() || pix->getInk() != oldInk)
			continue;

		if (saver)
			saver->save(p);

		pix->setInk(ink);

		seeds.push(TPoint(p.x - 1, p.y - 1));
		seeds.push(TPoint(p.x - 1, p.y));
		seeds.push(TPoint(p.x - 1, p.y + 1));
		seeds.push(TPoint(p.x, p.y - 1));
		seeds.push(TPoint(p.x, p.y + 1));
		seeds.push(TPoint(p.x + 1, p.y - 1));
		seeds.push(TPoint(p.x + 1, p.y));
		seeds.push(TPoint(p.x + 1, p.y + 1));
	}
	r->unlock();
}
  //! Elimina i segmenti che non sono contenuti all'interno dello stroke!!!
  void checkSegments(std::vector<TAutocloser::Segment> &segments,
                     TStroke *stroke, const TRasterCM32P &ras,
                     const TPoint &delta) {
    TVectorImage vi;
    TStroke *app = new TStroke();
    *app         = *stroke;
    app->transform(TTranslation(convert(ras->getCenter())));
    vi.addStroke(app);
    vi.findRegions();
    std::vector<TAutocloser::Segment>::iterator it = segments.begin();
    for (; it < segments.end(); it++) {
      if (it == segments.end()) break;

      int i;
      bool isContained = false;
      for (i = 0; i < (int)vi.getRegionCount(); i++) {
        TRegion *reg = vi.getRegion(i);
        if (reg->contains(convert(it->first + delta)) &&
            reg->contains(convert(it->second + delta))) {
          isContained = true;
          break;
        }
      }
      if (!isContained) {
        it = segments.erase(it);
        if (it != segments.end() && it != segments.begin())
          it--;
        else if (it == segments.end())
          break;
      }
    }
  }
Example #3
0
 InkSegmenter(const TRasterCM32P &r, float growFactor, TTileSaverCM32 *saver)
     : m_r(r)
     , m_lx(r->getLx())
     , m_ly(r->getLy())
     , m_wrap(r->getWrap())
     , m_buf((TPixelCM32 *)r->getRawData())
     , m_bBox(r->getBounds())
     , m_saver(saver)
     , m_growFactor(growFactor) {
   m_displaceVector[0] = -m_wrap - 1;
   m_displaceVector[1] = -m_wrap;
   m_displaceVector[2] = -m_wrap + 1;
   m_displaceVector[3] = -1;
   m_displaceVector[4] = +1;
   m_displaceVector[5] = m_wrap - 1;
   m_displaceVector[6] = m_wrap;
   m_displaceVector[7] = m_wrap + 1;
 }
Example #4
0
void InkSegmenter::drawSegment(
    const TPoint &p0, const TPoint &p1, int ink,
    /*vector<pair<TPixelCM32*, int> >& oldInks,*/ TTileSaverCM32 *saver) {
  int x, y, dx, dy, d, incr_1, incr_2;

  int x1 = p0.x;
  int y1 = p0.y;
  int x2 = p1.x;
  int y2 = p1.y;

  if (x1 > x2) {
    tswap(x1, x2);
    tswap(y1, y2);
  }

  TPixelCM32 *buf = m_r->pixels() + y1 * m_wrap + x1;
  /*if (buf->getInk()!=damInk)
          oldInks.push_back(pair<TPixelCM32*, int>(buf, buf->getInk()));
  if ((m_r->pixels() + y2*m_wrap + x2)->getInk()!=damInk)
          oldInks.push_back(pair<TPixelCM32*, int>(m_r->pixels() + y2*m_wrap +
  x2, (m_r->pixels() + y2*m_wrap + x2)->getInk()));*/

  if (saver) {
    saver->save(p0);
    saver->save(p1);
  }

  buf->setInk(ink);
  (m_r->pixels() + y2 * m_wrap + x2)->setInk(ink);

  dx = x2 - x1;
  dy = y2 - y1;

  x = y = 0;

  if (dy >= 0) {
    if (dy <= dx)
      DRAW_SEGMENT(x, y, dx, dy, (buf++), (buf += m_wrap + 1), SET_INK)
    else
      DRAW_SEGMENT(y, x, dy, dx, (buf += m_wrap), (buf += m_wrap + 1), SET_INK)
  } else {
Example #5
0
void Convert2Tlv::buildInksFromGrayTones(TRasterCM32P &rout, const TRasterP &rin)
{
	int i, j;

	TRasterGR8P r8 = (TRasterGR8P)rin;
	TRaster32P r32 = (TRaster32P)rin;
	if (r8)
		for (i = 0; i < rin->getLy(); i++) {
			TPixelGR8 *pixin = r8->pixels(i);
			TPixelCM32 *pixout = rout->pixels(i);
			for (j = 0; j < rin->getLx(); j++, pixin++, pixout++)
				*pixout = TPixelCM32(1, 0, pixin->value);
		}
	else
		for (i = 0; i < rin->getLy(); i++) {
			TPixel *pixin = r32->pixels(i);
			TPixelCM32 *pixout = rout->pixels(i);
			for (j = 0; j < rin->getLx(); j++, pixin++, pixout++)
				*pixout = TPixelCM32(1, 0, TPixelGR8::from(*pixin).value);
		}
}
Example #6
0
// Copies the cmIn paint and ink colors to the output rasters.
void buildLayers(const TRasterCM32P &cmIn,
                 const std::vector<TPixel32> &palColors, TRaster32P &inkRaster,
                 TRaster32P &paintRaster) {
  // Separate cmIn by copying the ink & paint colors directly to the layer
  // rasters.
  TPixelCM32 *cmPix, *cmBegin = (TPixelCM32 *)cmIn->getRawData();
  TPixel32 *inkPix   = (TPixel32 *)inkRaster->getRawData();
  TPixel32 *paintPix = (TPixel32 *)paintRaster->getRawData();

  unsigned int i, j, lx = cmIn->getLx(), ly = cmIn->getLy(),
                     wrap = cmIn->getWrap();
  for (i = 0; i < ly; ++i) {
    cmPix = cmBegin + i * wrap;

    for (j = 0; j < lx; ++j, ++cmPix, ++inkPix, ++paintPix) {
      *inkPix   = palColors[cmPix->getInk()];
      *paintPix = palColors[cmPix->getPaint()];

      // Should pure colors be checked...?
    }
  }
}
Example #7
0
// Returns true or false whether the selectedColor is the only selectable color
// in the neighbourhood. If so, the blend copies it to the output layer pixel
// directly.
inline bool isFlatNeighbourhood(int selectedColor, const TRasterCM32P &cmIn,
                                const TPoint &pos,
                                const SelectionRaster &selRas,
                                const BlurPattern &blurPattern) {
  TPixelCM32 &pix = cmIn->pixels(pos.y)[pos.x];
  int lx = cmIn->getLx(), ly = cmIn->getLy();
  unsigned int xy;

  TPoint samplePix;

  const TPoint *samplePoint =
      blurPattern.m_samples.empty() ? 0 : &blurPattern.m_samples[0];

  // Read the samples to determine if they only have posSelectedColor
  unsigned int i, samplesCount = blurPattern.m_samples.size();
  for (i = 0; i < samplesCount; ++i, ++samplePoint) {
    // Make sure the sample is inside the image
    samplePix.x = pos.x + samplePoint->x;
    samplePix.y = pos.y + samplePoint->y;

    xy = samplePix.x + lx * samplePix.y;

    if (samplePix.x < 0 || samplePix.y < 0 || samplePix.x >= lx ||
        samplePix.y >= ly)
      continue;

    if (!selRas.isPurePaint(xy) && selRas.isSelectedInk(xy))
      if (cmIn->pixels(samplePix.y)[samplePix.x].getInk() != selectedColor)
        return false;

    if (!selRas.isPureInk(xy) && selRas.isSelectedPaint(xy))
      if (cmIn->pixels(samplePix.y)[samplePix.x].getPaint() != selectedColor)
        return false;
  }

  return true;
}
Example #8
0
//-----------------------------------------------------------------------------
// questa funzione viene chiamata dopo il fill rect delle aree, e colora gli
// inchiostri di tipo "autoink"
// che confinano con le aree appena fillate con il rect. rbefore e' il rect del
// raster prima del rectfill.
void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore,
                  TPalette *plt) {
  assert(plt);
  TRasterCM32P r = rin->extract(rect);
  assert(r->getSize() == rbefore->getSize());
  int i, j;

  for (i = 0; i < r->getLy(); i++) {
    TPixelCM32 *pix  = r->pixels(i);
    TPixelCM32 *pixb = rbefore->pixels(i);
    for (j = 0; j < r->getLx(); j++, pix++, pixb++) {
      int paint = pix->getPaint();
      int tone  = pix->getTone();
      int ink   = pix->getInk();
      if (paint != pixb->getPaint() && tone > 0 && tone < 255 && ink != paint &&
          plt->getStyle(ink)->getFlags() != 0)
        inkFill(rin, TPoint(j, i) + rect.getP00(), paint, 0, NULL, &rect);
    }
  }
}
Example #9
0
void Convert2Tlv::buildInksForNAAImage(TRasterCM32P &rout, const TRaster32P &rin)
{
	std::map<TPixel, int>::iterator it;
	TPixel curColor = TPixel::Transparent;
	int i, j;
	int curIndex;

	//prima passata: identifico i colori di inchiostro e metto in rout i pixel di inchiostro puro
	for (i = 0; i < rin->getLy(); i++) {
		TPixel *pixin = rin->pixels(i);
		TPixelCM32 *pixout = rout->pixels(i);
		for (j = 0; j < rin->getLx(); j++, pixin++, pixout++) {
			TPixel colorIn;

			/*- treat white/transparent pixels as transparent -*/
			if (*pixin == TPixel(255, 255, 255) || *pixin == TPixel::Transparent) {
				*pixout = TPixelCM32(0, 0, 255);
				continue;
			}

			if (curColor != *pixin) {
				curColor = *pixin;
				if ((it = m_colorMap.find(curColor)) == m_colorMap.end()) {
					if (m_lastIndex < 4095)
						m_colorMap[curColor] = ++m_lastIndex;
					curIndex = m_lastIndex;
				} else
					curIndex = it->second;
			}
			*pixout = TPixelCM32(curIndex, 0, 0);
		}
	}

	if (m_colorMap.empty())
		m_colorMap[TPixel::Black] = ++m_lastIndex;
}
Example #10
0
void SelectionRaster::updateSelection(TRasterCM32P cm,
                                      const BlendParam &param) {
  // Make a hard copy of color indexes. We do so since we absolutely prefer
  // having them SORTED!
  std::vector<int> cIndexes = param.colorsIndexes;
  std::sort(cIndexes.begin(), cIndexes.end());

  unsigned int lx = cm->getLx(), ly = cm->getLy(), wrap = cm->getWrap();

  // Scan each cm pixel, looking if its ink or paint is in param's colorIndexes.
  cm->lock();
  TPixelCM32 *pix, *pixBegin = (TPixelCM32 *)cm->getRawData();

  SelectionData *selData = data();

  const int *v =
      &cIndexes[0];  // NOTE: cIndexes.size() > 0 due to external check.
  unsigned int vSize = cIndexes.size();
  unsigned int i, j;

  // NOTE: It seems that linear searches are definitely best for small color
  // indexes.
  if (vSize > 50) {
    for (i = 0; i < ly; ++i) {
      pix = pixBegin + i * wrap;
      for (j = 0; j < lx; ++j, ++pix, ++selData) {
        selData->m_selectedInk   = binarySearch(v, vSize, pix->getInk());
        selData->m_selectedPaint = binarySearch(v, vSize, pix->getPaint());
      }
    }
  } else {
    for (i = 0; i < ly; ++i) {
      pix = pixBegin + i * wrap;
      for (j = 0; j < lx; ++j, ++pix, ++selData) {
        selData->m_selectedInk   = linearSearch(v, vSize, pix->getInk());
        selData->m_selectedPaint = linearSearch(v, vSize, pix->getPaint());
      }
    }
  }

  cm->unlock();
}
Example #11
0
SelectionRaster::SelectionRaster(TRasterCM32P cm) {
  unsigned int lx = cm->getLx(), ly = cm->getLy(), wrap = cm->getWrap();
  unsigned int size = lx * ly;

  m_wrap = lx;

  m_selection.allocate(size);

  cm->lock();
  TPixelCM32 *pix, *pixBegin = (TPixelCM32 *)cm->getRawData();

  SelectionData *selData = data();

  unsigned int i, j;
  for (i = 0; i < ly; ++i) {
    pix = pixBegin + i * wrap;
    for (j = 0; j < lx; ++j, ++pix, ++selData) {
      selData->m_pureInk   = pix->getTone() == 0;
      selData->m_purePaint = pix->getTone() == 255;
    }
  }

  cm->unlock();
}
Example #12
0
void OutlineVectorizer::makeDataRaster(const TRasterP &src)
{
	m_vimage = new TVectorImage();
	if (!src)
		return;
	m_src = src;

	clearNodes();
	clearJunctions();

	int x, y, ii = 0;
	TRaster32P srcRGBM = (TRaster32P)m_src;
	TRasterCM32P srcCM = (TRasterCM32P)m_src;
	TRasterGR8P srcGR = (TRasterGR8P)m_src;

	// Inizializzo DataRasterP per i casi in cui si ha un TRaster32P, un TRasterGR8P o un TRasterCM32P molto grande
	DataRasterP dataRaster(m_src->getSize().lx + 2, m_src->getSize().ly + 2);
	if (srcRGBM || srcGR || (srcCM && srcCM->getLx() * srcCM->getLy() > 5000000)) {
		int ly = dataRaster->getLy();
		int lx = dataRaster->getLx();
		int wrap = dataRaster->getWrap();
		DataPixel *dataPix0 = dataRaster->pixels(0);
		DataPixel *dataPix1 = dataRaster->pixels(0) + m_src->getLx() + 1;
		for (y = 0; y < ly; y++, dataPix0 += wrap, dataPix1 += wrap) {
			dataPix0->m_pos.x = 0;
			dataPix1->m_pos.x = lx - 1;
			dataPix0->m_pos.y = dataPix1->m_pos.y = y;
			dataPix0->m_value = dataPix1->m_value = 0;
			dataPix0->m_ink = dataPix1->m_ink = false;
			dataPix0->m_node = dataPix1->m_node = 0;
		}
		dataPix0 = dataRaster->pixels(0);
		dataPix1 = dataRaster->pixels(ly - 1);
		for (x = 0; x < lx; x++, dataPix0++, dataPix1++) {
			dataPix0->m_pos.x = dataPix1->m_pos.x = x;
			dataPix0->m_pos.y = 0;
			dataPix1->m_pos.y = ly - 1;
			dataPix0->m_value = dataPix1->m_value = 0;
			dataPix0->m_ink = dataPix1->m_ink = false;
			dataPix0->m_node = dataPix1->m_node = 0;
		}
	}

	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()) {
			inkId = m_palette->getStyleCount();
			m_palette->getStylePage(1)->insertStyle(1, m_configuration.m_inkColor);
			m_palette->setStyle(inkId, m_configuration.m_inkColor);
		}
		assert(inkId);

		m_dataRasterArray.push_back(std::pair<int, DataRasterP>(inkId, dataRaster));
		int maxDistance2 = m_configuration.m_threshold * m_configuration.m_threshold;

		for (y = 0; y < m_src->getLy(); y++) {
			TPixel32 *inPix = srcRGBM->pixels(y);
			TPixel32 *inEndPix = inPix + srcRGBM->getLx();
			DataPixel *dataPix = dataRaster->pixels(y + 1) + 1;
			x = 0;
			while (inPix < inEndPix) {
				*dataPix = DataPixel();
				int distance2 = colorDistance2(m_configuration.m_inkColor, *inPix);

				if (y == 0 || y == m_src->getLy() - 1 || x == 0 || x == m_src->getLx() - 1 || inPix->m == 0) {
					dataPix->m_value = 255;
					dataPix->m_ink = false;
				} else {
					dataPix->m_value = (inPix->r + 2 * inPix->g + inPix->b) >> 2;
					dataPix->m_ink = (distance2 < maxDistance2);
				}
				dataPix->m_pos.x = x++;
				dataPix->m_pos.y = y;
				dataPix->m_node = 0;
				inPix++;
				dataPix++;
			}
		}
	} else if (srcGR) {
Example #13
0
// Performs a single color blending. This function can be repeatedly invoked to
// perform multiple color blending.
inline void doBlend(const TRasterCM32P &cmIn, RGBMRasterPair &inkLayer,
                    RGBMRasterPair &paintLayer, const SelectionRaster &selRas,
                    const std::vector<BlurPattern> &blurPatterns) {
  // Declare some vars
  unsigned int blurPatternsCount = blurPatterns.size();
  int lx = cmIn->getLx(), ly = cmIn->getLy();
  double totalFactor;

  TPixelCM32 *cmPix, *cmBegin = (TPixelCM32 *)cmIn->getRawData();

  TPixel32 *inkIn    = (TPixel32 *)inkLayer.first->getRawData(),
           *inkOut   = (TPixel32 *)inkLayer.second->getRawData(),
           *paintIn  = (TPixel32 *)paintLayer.first->getRawData(),
           *paintOut = (TPixel32 *)paintLayer.second->getRawData();

  const BlurPattern *blurPattern, *blurPatternsBegin = &blurPatterns[0];
  bool builtSamples = false;

  DoubleRGBMPixel samplesSum;

  // For every cmIn pixel
  TPoint pos;
  SelectionData *selData = selRas.data();
  cmPix                  = cmBegin;
  for (pos.y = 0; pos.y < ly;
       ++pos.y, cmPix = cmBegin + pos.y * cmIn->getWrap())
    for (pos.x = 0; pos.x < lx; ++pos.x, ++inkIn, ++inkOut, ++paintIn,
        ++paintOut, ++selData, ++cmPix) {
      blurPattern = blurPatternsBegin + (rand() % blurPatternsCount);

      // Build the ink blend color
      if (!selData->m_purePaint && selData->m_selectedInk) {
        if (!builtSamples) {
          // Build samples contributes
          totalFactor  = 1.0;
          samplesSum.r = samplesSum.g = samplesSum.b = samplesSum.m = 0.0;

          if (!isFlatNeighbourhood(cmPix->getInk(), cmIn, pos, selRas,
                                   *blurPattern))
            addSamples(cmIn, pos, inkLayer.first, paintLayer.first, selRas,
                       *blurPattern, samplesSum, totalFactor);

          builtSamples = true;
        }

        // Output the blended pixel
        inkOut->r = (samplesSum.r + inkIn->r) / totalFactor;
        inkOut->g = (samplesSum.g + inkIn->g) / totalFactor;
        inkOut->b = (samplesSum.b + inkIn->b) / totalFactor;
        inkOut->m = (samplesSum.m + inkIn->m) / totalFactor;
      } else {
        // If the color is not blended, then just copy the old layer pixel
        *inkOut = *inkIn;
      }

      // Build the paint blend color
      if (!selData->m_pureInk && selData->m_selectedPaint) {
        if (!builtSamples) {
          // Build samples contributes
          totalFactor  = 1.0;
          samplesSum.r = samplesSum.g = samplesSum.b = samplesSum.m = 0.0;

          if (!isFlatNeighbourhood(cmPix->getPaint(), cmIn, pos, selRas,
                                   *blurPattern))
            addSamples(cmIn, pos, inkLayer.first, paintLayer.first, selRas,
                       *blurPattern, samplesSum, totalFactor);

          builtSamples = true;
        }

        // Output the blended pixel
        paintOut->r = (samplesSum.r + paintIn->r) / totalFactor;
        paintOut->g = (samplesSum.g + paintIn->g) / totalFactor;
        paintOut->b = (samplesSum.b + paintIn->b) / totalFactor;
        paintOut->m = (samplesSum.m + paintIn->m) / totalFactor;
      } else {
        // If the color is not blended, then just copy the old layer pixel
        *paintOut = *paintIn;
      }

      builtSamples = false;
    }
}
Example #14
0
// Calculates the estimate of blend selection in the neighbourhood specified by
// blurPattern.
inline void addSamples(const TRasterCM32P &cmIn, const TPoint &pos,
                       const TRaster32P &inkRas, const TRaster32P &paintRas,
                       const SelectionRaster &selRas,
                       const BlurPattern &blurPattern, DoubleRGBMPixel &pixSum,
                       double &factorsSum) {
  double inkFactor, paintFactor;
  unsigned int xy, j, l;
  int lx = cmIn->getLx(), ly = cmIn->getLy();
  TPixel32 *color;
  TPoint samplePos, pathPos;

  const TPoint *samplePoint =
      blurPattern.m_samples.empty() ? 0 : &blurPattern.m_samples[0];
  const TPoint *pathPoint;

  unsigned int i, blurSamplesCount = blurPattern.m_samples.size();
  for (i = 0; i < blurSamplesCount; ++i, ++samplePoint) {
    // Add each samples contribute to the sum
    samplePos.x = pos.x + samplePoint->x;
    samplePos.y = pos.y + samplePoint->y;
    if (samplePos.x < 0 || samplePos.y < 0 || samplePos.x >= lx ||
        samplePos.y >= ly)
      continue;

    // Ensure that each pixel on the sample's path (if any) is selected
    l         = blurPattern.m_samplePaths[i].size();
    pathPoint = blurPattern.m_samplePaths[i].empty()
                    ? 0
                    : &blurPattern.m_samplePaths[i][0];
    for (j = 0; j < l; ++j, ++pathPoint) {
      pathPos.x = pos.x + pathPoint->x;
      pathPos.y = pos.y + pathPoint->y;
      xy        = pathPos.x + lx * pathPos.y;

      if (!(selRas.isPurePaint(xy) || selRas.isSelectedInk(xy))) break;

      if (!(selRas.isPureInk(xy) || selRas.isSelectedPaint(xy))) break;
    }

    if (j < l) continue;

    xy = samplePos.x + lx * samplePos.y;

    if (selRas.isSelectedInk(xy) && !selRas.isPurePaint(xy)) {
      getFactors(cmIn->pixels(samplePos.y)[samplePos.x].getTone(), inkFactor,
                 paintFactor);

      color = &inkRas->pixels(samplePos.y)[samplePos.x];
      pixSum.r += inkFactor * color->r;
      pixSum.g += inkFactor * color->g;
      pixSum.b += inkFactor * color->b;
      pixSum.m += inkFactor * color->m;
      factorsSum += inkFactor;
    }

    if (selRas.isSelectedPaint(xy) && !selRas.isPureInk(xy)) {
      getFactors(cmIn->pixels(samplePos.y)[samplePos.x].getTone(), inkFactor,
                 paintFactor);

      color = &paintRas->pixels(samplePos.y)[samplePos.x];
      pixSum.r += paintFactor * color->r;
      pixSum.g += paintFactor * color->g;
      pixSum.b += paintFactor * color->b;
      pixSum.m += paintFactor * color->m;
      factorsSum += paintFactor;
    }
  }
}
Example #15
0
void TRop::over(TRasterP rout, const TRasterCM32P &rup, TPalette *palette, const TPoint &point, const TAffine &aff)
{
	TRaster32P app(rup->getSize());
	TRop::convert(app, rup, palette);
	TRop::over(rout, app, point, aff);
}
Example #16
0
void Convert2Tlv::buildToonzRaster(TRasterCM32P &rout, const TRasterP &rin1, const TRasterP &rin2)
{
	if (rin2)
		assert(rin1->getSize() == rin2->getSize());

	rout->clear();

	std::cout << "      computing inks...\n";
	TRaster32P r1 = (TRaster32P)rin1;
	TRasterGR8P r1gr = (TRasterGR8P)rin1;
	TRaster32P r2 = (TRaster32P)rin2;
	TRasterGR8P r2gr = (TRasterGR8P)rin2;
	TRasterP rU, rP;

	if (r1gr) {
		rU = r1gr;
		rP = r2;
	} else if (r2gr) {
		rU = r2gr;
		rP = r1;
	} else if (!r1)
		rU = r2;
	else if (!r2)
		rU = r1;
	else if (firstIsUnpainted(r1, r2)) {
		rU = r1;
		rP = r2;
	} else {
		rU = r2;
		rP = r1;
	}

	TRasterCM32P r;
	if (rout->getSize() != rU->getSize()) {
		int dx = rout->getLx() - rU->getLx();
		int dy = rout->getLy() - rU->getLy();
		assert(dx >= 0 && dy >= 0);

		r = rout->extract(dx / 2, dy / 2, dx / 2 + rU->getLx() - 1, dy / 2 + rU->getLy() - 1);
	} else
		r = rout;

	if ((TRasterGR8P)rU)
		buildInksFromGrayTones(r, rU);
	else if (m_isUnpaintedFromNAA)
		buildInksForNAAImage(r, (TRaster32P)rU);
	else {
		int maxMatte = getMaxMatte((TRaster32P)rU);
		if (maxMatte == -1)
			buildInksFromGrayTones(r, rU);
		else {
			if (maxMatte < 255)
				normalize(rU, maxMatte);
			buildInks(r, (TRaster32P)rU /*rP,*/);
		}
	}

	if (m_autoclose)
		TAutocloser(r, AutocloseDistance, AutocloseAngle, 1, AutocloseOpacity).exec();

	if (rP) {
		std::cout << "      computing paints...\n";
		doFill(r, rP);
	}
	if (m_antialiasType == 2) //remove antialias
		removeAntialias(r);
	else if (m_antialiasType == 1) //add antialias
	{
		TRasterCM32P raux(r->getSize());
		TRop::antialias(r, raux, 10, m_antialiasValue);
		rout = raux;
	}
}
Example #17
0
void Convert2Tlv::doFill(TRasterCM32P &rout, const TRaster32P &rin)
{
	//prima passata: si filla  solo partendo da pixel senza inchiostro, senza antialiasing(tone==255)
	for (int i = 0; i < rin->getLy(); i++) {
		TPixel *pixin = rin->pixels(i);
		TPixelCM32 *pixout = rout->pixels(i);
		for (int j = 0; j < rin->getLx(); j++, pixin++, pixout++) {
			if (!(pixout->getTone() == 255 && pixout->getPaint() == 0 && pixin->m == 255))
				continue;

			std::map<TPixel, int>::const_iterator it;
			int paintIndex;
			if ((it = m_colorMap.find(*pixin)) == m_colorMap.end()) {
				if (m_colorTolerance > 0)
					it = findNearestColor(*pixin);
				// if (it==colorMap.end() && (int)colorMap.size()>origColorCount) //se non l'ho trovato tra i colori origari, lo cerco in quelli nuovi, ma in questo caso deve essere esattamente uguale(tolerance = 0)
				//	 it  = findNearestColor(*pixin, colorMap, colorTolerance, origColorCount, colorMap.size()-1);

				if (it == m_colorMap.end() && m_lastIndex < 4096) {
					m_colorMap[*pixin] = ++m_lastIndex;
					paintIndex = m_lastIndex;
				} else if (it != m_colorMap.end()) {
					m_colorMap[*pixin] = it->second;
					paintIndex = it->second;
				}
			} else
				paintIndex = it->second;
			FillParameters params;
			params.m_p = TPoint(j, i);
			params.m_styleId = paintIndex;
			params.m_emptyOnly = true;
			fill(rout, params);
			//if (*((ULONG *)rout->getRawData())!=0xff)
			//  {
			//  int cavolo=0;
			//  }
		}
	}

	//seconda passata: se son rimasti pixel antialiasati non fillati, si fillano, cercando nelle vicinanze un pixel di paint puro per capire il colore da usare
	for (int i = 0; i < rin->getLy(); i++) {
		TPixel *pixin = rin->pixels(i);
		TPixelCM32 *pixout = rout->pixels(i);
		for (int j = 0; j < rin->getLx(); j++, pixin++, pixout++) {
			if (!(pixout->getTone() > 0 && pixout->getTone() < 255 && pixout->getPaint() == 0 && pixin->m == 255))
				continue;

			TPoint p = getClosestPurePaint(rout, i, j);
			if (p.x == -1)
				continue;

			//pixout->setPaint( paintIndex);
			FillParameters params;
			params.m_p = TPoint(j, i);
			params.m_styleId = (rout->pixels(p.y) + p.x)->getPaint();
			params.m_emptyOnly = true;

			fill(rout, params);
		}
	}

	//infine, si filla di trasparente lo sfondo, percorrendo il bordo, nel caso di trasbordamenti di colore
	TPixelCM32 *pixCm;
	TPixel *pix;

	pixCm = rout->pixels(0);
	pix = rin->pixels(0);
	FillParameters params;
	params.m_styleId = 0;

	for (int i = 0; i < rout->getLx(); i++, pixCm++, pix++)
		if (pixCm->getTone() == 255 && pixCm->getPaint() != 0 && pix->m == 0) {
			params.m_p = TPoint(i, 0);
			fill(rout, params);
		}

	pixCm = rout->pixels(rout->getLy() - 1);
	pix = rin->pixels(rout->getLy() - 1);
	for (int i = 0; i < rout->getLx(); i++, pixCm++, pix++)
		if (pixCm->getTone() == 255 && pixCm->getPaint() != 0 && pix->m == 0) {
			params.m_p = TPoint(i, rout->getLy() - 1);
			fill(rout, params);
		}
	int wrapCM = rout->getWrap();
	int wrap = rin->getWrap();

	pixCm = rout->pixels(0);
	pix = rin->pixels(0);
	for (int i = 0; i < rin->getLy(); i++, pixCm += wrapCM, pix += wrap)
		if (pixCm->getTone() == 255 && pixCm->getPaint() != 0 && pix->m == 0) {
			params.m_p = TPoint(0, i);
			fill(rout, params);
		}
	pixCm = rout->pixels(0) + rout->getLx() - 1;
	pix = rin->pixels(0) + rin->getLx() - 1;
	for (int i = 0; i < rin->getLy(); i++, pixCm += wrapCM, pix += wrap)
		if (pixCm->getTone() == 255 && pixCm->getPaint() != 0 && pix->m == 0) {
			params.m_p = TPoint(rout->getLx() - 1, i);
			fill(rout, params);
		}
}
Example #18
0
void Convert2Tlv::buildInks(TRasterCM32P &rout, const TRaster32P &rin)
{
	std::map<TPixel, int>::const_iterator it;
	TPixel curColor = TPixel::Transparent;
	int i, j;
	int curIndex;

	//prima passata: identifico i colori di inchiostro e metto in rout i pixel di inchiostro puro
	for (i = 0; i < rin->getLy(); i++) {
		TPixel *pixin = rin->pixels(i);
		TPixelCM32 *pixout = rout->pixels(i);
		for (j = 0; j < rin->getLx(); j++, pixin++, pixout++) {
			TPixel colorIn;

			if (pixin->m != 255)
				continue;

			if (curColor != *pixin) {
				curColor = *pixin;
				if ((it = m_colorMap.find(curColor)) == m_colorMap.end()) {
					if (m_colorTolerance > 0)
						it = findNearestColor(curColor);
					//if (it==colorMap.end() && (int)colorMap.size()>origColorCount)
					//	it  = findNearestColor(curColor, colorMap, colorTolerance, origColorCount, colorMap.size()-1);
					if (it == m_colorMap.end() && m_lastIndex < 4095) {
						m_colorMap[curColor] = ++m_lastIndex;
						curIndex = m_lastIndex;
					} else if (it != m_colorMap.end()) {
						m_colorMap[curColor] = it->second;
						curIndex = it->second;
					}
				} else
					curIndex = it->second;
			}
			*pixout = TPixelCM32(curIndex, 0, 0);
		}
	}

	//seconda  passata: metto gli inchiostri di antialiasing
	curColor = TPixel::Transparent;

	for (i = 0; i < rin->getLy(); i++) {
		TPixel *pixin = rin->pixels(i);
		TPixelCM32 *pixout = rout->pixels(i);
		for (j = 0; j < rin->getLx(); j++, pixin++, pixout++) {
			TPixel colorIn;
			if (pixin->m == 255) //gia' messo nel ciclo precedente
				continue;
			if (pixin->m == 0)
				continue;

			colorIn = unmultiply(*pixin); //findClosestOpaque(rin, i, j);

			if (curColor != colorIn) {
				curColor = colorIn;
				if ((it = m_colorMap.find(curColor)) != m_colorMap.end())
					curIndex = it->second;
				else
					curIndex = findClosest(m_colorMap, curColor);
			}
			*pixout = TPixelCM32(curIndex, 0, 255 - pixin->m);
		}
	}
}
Example #19
0
/*-- 戻り値はsaveBoxが更新されたかどうか --*/
bool fill(const TRasterCM32P &r, const FillParameters &params,
          TTileSaverCM32 *saver) {
  TPixelCM32 *pix, *limit, *pix0, *oldpix;
  int oldy, xa, xb, xc, xd, dy;
  int oldxc, oldxd;
  int tone, oldtone;
  TPoint p = params.m_p;
  int x = p.x, y = p.y;
  int paint = params.m_styleId;
  int fillDepth =
      params.m_shiftFill ? params.m_maxFillDepth : params.m_minFillDepth;

  /*-- getBoundsは画像全面 --*/
  TRect bbbox = r->getBounds();

  /*- 画面外のクリックの場合はreturn -*/
  if (!bbbox.contains(p)) return false;
  /*- 既に同じ色が塗られている場合はreturn -*/
  if ((r->pixels(p.y) + p.x)->getPaint() == paint) return false;
  /*- 「透明部分だけを塗る」オプションが有効で、既に色が付いている場合はreturn
   * -*/
  if (params.m_emptyOnly && (r->pixels(p.y) + p.x)->getPaint() != 0)
    return false;

  assert(fillDepth >= 0 && fillDepth < 16);

  switch (TPixelCM32::getMaxTone()) {
  case 15:
    fillDepth = (15 - fillDepth);
    break;
  case 255:
    fillDepth = ((15 - fillDepth) << 4) | (15 - fillDepth);
    break;
  default:
    assert(false);
  }

  /*-- 四隅の色を見て、一つでも変わったらsaveBoxを更新する --*/
  TPixelCM32 borderIndex[4];
  TPixelCM32 *borderPix[4];
  pix            = r->pixels(0);
  borderPix[0]   = pix;
  borderIndex[0] = *pix;
  pix += r->getLx() - 1;
  borderPix[1]   = pix;
  borderIndex[1] = *pix;
  pix            = r->pixels(r->getLy() - 1);
  borderPix[2]   = pix;
  borderIndex[2] = *pix;
  pix += r->getLx() - 1;
  borderPix[3]   = pix;
  borderIndex[3] = *pix;

  std::stack<FillSeed> seeds;

  fillRow(r, p, xa, xb, paint, params.m_palette, saver);
  seeds.push(FillSeed(xa, xb, y, 1));
  seeds.push(FillSeed(xa, xb, y, -1));

  while (!seeds.empty()) {
    FillSeed fs = seeds.top();
    seeds.pop();

    xa   = fs.m_xa;
    xb   = fs.m_xb;
    oldy = fs.m_y;
    dy   = fs.m_dy;
    y    = oldy + dy;
    if (y > bbbox.y1 || y < bbbox.y0) continue;
    pix = pix0 = r->pixels(y) + xa;
    limit      = r->pixels(y) + xb;
    oldpix     = r->pixels(oldy) + xa;
    x          = xa;
    oldxd      = (std::numeric_limits<int>::min)();
    oldxc      = (std::numeric_limits<int>::max)();
    while (pix <= limit) {
      oldtone = threshTone(*oldpix, fillDepth);
      tone    = threshTone(*pix, fillDepth);
      if (pix->getPaint() != paint && tone <= oldtone && tone != 0) {
        fillRow(r, TPoint(x, y), xc, xd, paint, params.m_palette, saver);
        if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy));
        if (xd > xb) seeds.push(FillSeed(xb + 1, xd, y, -dy));
        if (oldxd >= xc - 1)
          oldxd = xd;
        else {
          if (oldxd >= 0) seeds.push(FillSeed(oldxc, oldxd, y, dy));
          oldxc = xc;
          oldxd = xd;
        }
        pix += xd - x + 1;
        oldpix += xd - x + 1;
        x += xd - x + 1;
      } else {
        pix++;
        oldpix++, x++;
      }
    }
    if (oldxd > 0) seeds.push(FillSeed(oldxc, oldxd, y, dy));
  }

  bool saveBoxChanged = false;
  for (int i = 0; i < 4; i++) {
    if (!((*borderPix[i]) == borderIndex[i])) {
      saveBoxChanged = true;
      break;
    }
  }
  return saveBoxChanged;
}
CleanupPreprocessedImage *TCleanupper::process(
	TRasterImageP &image, bool first_image, TRasterImageP &onlyResampledImage,
	bool isCameraTest, bool returnResampled, bool onlyForSwatch, TAffine *resampleAff)
{
	TAffine aff;
	double blur;
	TDimension outDim(0, 0);
	TPointD outDpi;

	bool isSameDpi = false;
	bool autocentered = getResampleValues(image, aff, blur, outDim, outDpi, isCameraTest, isSameDpi);
	if (m_parameters->m_autocenterType != AUTOCENTER_NONE && !autocentered)
		DVGui::MsgBox(DVGui::WARNING, QObject::tr("The autocentering failed on the current drawing."));

	bool fromGr8 = (bool)TRasterGR8P(image->getRaster());
	bool toGr8 = (m_parameters->m_lineProcessingMode == lpGrey);

	// If necessary, perform auto-adjust
	if (!isCameraTest && m_parameters->m_lineProcessingMode != lpNone && toGr8 && m_parameters->m_autoAdjustMode != AUTO_ADJ_NONE &&
		!onlyForSwatch) {
		static int ref_cum[256];
		UCHAR lut[256];
		int cum[256];
		double x0_src_f, y0_src_f, x1_src_f, y1_src_f;
		int x0_src, y0_src, x1_src, y1_src;

		//cleanup_message("Autoadjusting... \n");

		TAffine inv = aff.inv();

		x0_src_f = affMV1(inv, 0, 0);
		y0_src_f = affMV2(inv, 0, 0);
		x1_src_f = affMV1(inv, outDim.lx - 1, outDim.ly - 1);
		y1_src_f = affMV2(inv, outDim.lx - 1, outDim.ly - 1);

		x0_src = tround(x0_src_f);
		y0_src = tround(y0_src_f);
		x1_src = tround(x1_src_f);
		y1_src = tround(y1_src_f);

		set_autoadjust_window(x0_src, y0_src, x1_src, y1_src);

		if (!TRasterGR8P(image->getRaster())) {
			//Auto-adjusting a 32-bit image. This means that a white background must be introduced first.
			TRaster32P ras32(image->getRaster()->clone());
			TRop::addBackground(ras32, TPixel32::White);
			image = TRasterImageP(ras32); //old image is released here
			ras32 = TRaster32P();

			TRasterGR8P rgr(image->getRaster()->getSize());
			TRop::copy(rgr, image->getRaster());

			//This is now legit. It was NOT before the clone, since the original could be cached.
			image->setRaster(rgr);
		}
		switch (m_parameters->m_autoAdjustMode) {
		case AUTO_ADJ_HISTOGRAM: {
			if (first_image) {
				build_gr_cum(image, ref_cum);
			} else {
				build_gr_cum(image, cum);
				build_gr_lut(ref_cum, cum, lut);
				apply_lut(image, lut);
			}
		}

			CASE AUTO_ADJ_HISTO_L : histo_l_algo(image, first_image);

			CASE AUTO_ADJ_BLACK_EQ : black_eq_algo(image);

			CASE AUTO_ADJ_NONE : DEFAULT : assert(false);
		}
	}

	fromGr8 = (bool)TRasterGR8P(image->getRaster()); //may have changed type due to auto-adjust

	assert(returnResampled || !onlyForSwatch); //if onlyForSwatch, then returnResampled

	// Allocate output colormap raster
	TRasterCM32P finalRas;
	if (!onlyForSwatch) {
		finalRas = TRasterCM32P(outDim);
		if (!finalRas) {
			TImageCache::instance()->outputMap(outDim.lx * outDim.ly * 4, "C:\\cachelog");
			assert(!"failed finalRas allocation!");
			return 0;
		}
	}

	// In case the input raster was a greymap, we cannot reutilize finalRas's buffer to transform the final
	// fullcolor pixels to colormap pixels directly (1 32-bit pixel would hold 4 8-bit pixels) - therefore,
	// a secondary greymap is allocated.

	//NOTE: This should be considered obsolete? By using TRop::resample( <TRaster32P& instance> , ...) we
	//should get the same effect!!

	TRasterP tmp_ras;

	if (returnResampled || (fromGr8 && toGr8)) {
		if (fromGr8 && toGr8)
			tmp_ras = TRasterGR8P(outDim);
		else
			tmp_ras = TRaster32P(outDim);

		if (!tmp_ras) {
			TImageCache::instance()->outputMap(outDim.lx * outDim.ly * 4, "C:\\cachelog");
			assert(!"failed tmp_ras allocation!");
			return 0;
		}
	} else
		//if finalRas is allocated, and the intermediate raster has to be 32-bit, we can perform pixel
		//conversion directly on the same output buffer
		tmp_ras = TRaster32P(outDim.lx, outDim.ly, outDim.lx, (TPixel32 *)finalRas->getRawData());

	TRop::ResampleFilterType flt_type;
	if (isSameDpi)
		flt_type = TRop::ClosestPixel; //NearestNeighbor
	else if (isCameraTest)
		flt_type = TRop::Triangle;
	else
		flt_type = TRop::Hann2;
	TRop::resample(tmp_ras, image->getRaster(), aff, flt_type, blur);

	if ((TRaster32P)tmp_ras)
		//Add white background to deal with semitransparent pixels
		TRop::addBackground(tmp_ras, TPixel32::White);

	if (resampleAff)
		*resampleAff = aff;

	image->getRaster()->unlock();
	image = TRasterImageP();

	if (returnResampled) {
		onlyResampledImage = TRasterImageP(tmp_ras);
		onlyResampledImage->setDpi(outDpi.x, outDpi.y);
	}

	if (onlyForSwatch)
		return 0;

	assert(finalRas);

	// Copy current cleanup palette to parameters' colors
	m_parameters->m_colors.update(m_parameters->m_cleanupPalette.getPointer(), m_parameters->m_noAntialias);

	if (toGr8) {
		//No (color) processing. Not even thresholding. This just means that all the important
		//stuff here is made in the brightness/contrast stage...

		//NOTE: Most of the color processing should be DISABLED in this case!!

		tmp_ras->lock();
		finalRas->lock();
		assert(tmp_ras->getSize() == finalRas->getSize());
		assert(tmp_ras->getLx() == tmp_ras->getWrap());
		assert(finalRas->getLx() == finalRas->getWrap());

		int pixCount = outDim.lx * outDim.ly;

		if (fromGr8) {
			UCHAR *rowin = tmp_ras->getRawData();
			TUINT32 *rowout = reinterpret_cast<TUINT32 *>(finalRas->getRawData());
			for (int i = 0; i < pixCount; i++)
				*rowout++ = *rowin++; //Direct copy for now... :(
		} else {
			TPixel32 *rowin = reinterpret_cast<TPixel32 *>(tmp_ras->getRawData());
			TUINT32 *rowout = reinterpret_cast<TUINT32 *>(finalRas->getRawData());
			for (int i = 0; i < pixCount; i++)
				*rowout++ = TPixelGR8::from(*rowin++).value;
		}

		tmp_ras->unlock();
		finalRas->unlock();
	} else {
		//WARNING: finalRas and tmp_ras may share the SAME buffer!
		assert(TRaster32P(tmp_ras));
		preprocessColors(finalRas, tmp_ras, m_parameters->m_colors);
	}

	TToonzImageP final;
	final = TToonzImageP(finalRas, finalRas->getBounds());
Example #21
0
TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, int inkId, wchar_t charcode, wchar_t nextCharCode) const
{
	TRasterGR8P grayAppImage;
	TPoint glyphOrig = appDrawChar(grayAppImage, m_pimpl->m_hdc, charcode);

	if (glyphOrig.x < 0) {
		glyphOrigin.x = glyphOrig.x;
		glyphOrig.x = 0;
	} else
		glyphOrigin.x = 0;

	if (glyphOrig.y < 0) {
		glyphOrigin.y = glyphOrig.y;
		glyphOrig.y = 0;
	} else
		glyphOrigin.y = 0;

	int srcLx = grayAppImage->getLx();
	int srcLy = grayAppImage->getLy();

	int dstLx = srcLx + glyphOrig.x;
	int dstLy = getMaxHeight();

	outImage = TRasterCM32P(dstLx, dstLy);
	outImage->clear();

	assert(TPixelCM32::getMaxTone() == 255);
	// TPixelCM32 bgColor(BackgroundStyle,BackgroundStyle,TPixelCM32::getMaxTone());
	TPixelCM32 bgColor;

	int ty = m_pimpl->m_metrics.tmDescent - 1 + glyphOrig.y;
	assert(ty < dstLy);
	assert(ty >= srcLy - 1);
	grayAppImage->lock();
	outImage->lock();

	for (int sy = 0; sy < srcLy; ++sy, --ty) {
		TPixelGR8 *srcPix = grayAppImage->pixels(sy);
		TPixelCM32 *tarPix = outImage->pixels(ty) + glyphOrig.x;
		for (int x = 0; x < srcLx; ++x) {
			int tone = 256 - (srcPix->value << 2);

			// grayScale  ToonzImage tone   Meaning
			//         0  255               Bg = PurePaint
			//         1  252
			//                 ...
			//        63    4
			//        64    0               Fg = Pure Ink

			if (tone < 0)
				tone = 0;

			if (tone >= 255)
				*tarPix = bgColor;
			else
				*tarPix = TPixelCM32(inkId, 0, tone); // BackgroundStyle,tone);

			++srcPix;
			++tarPix;
		}
	}
	grayAppImage->unlock();
	outImage->unlock();

	return getDistance(charcode, nextCharCode);
}