//this one incorporate the preprocessColors and the finalize function; used for swatch.(tipically on very small rasters)
TRasterP TCleanupper::processColors(const TRasterP &rin)
{
	if (m_parameters->m_lineProcessingMode == lpNone)
		return rin;

	TRasterCM32P rcm = TRasterCM32P(rin->getSize());
	if (!rcm) {
		assert(!"failed finalRas allocation!");
		return TRasterCM32P();
	}

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

	bool toGr8 = (m_parameters->m_lineProcessingMode == lpGrey);
	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!!

		//finalRas->clear();
		rin->lock();
		rcm->lock();

		if (TRasterGR8P(rin)) {
			UCHAR *rowin = rin->getRawData();
			TUINT32 *rowout = reinterpret_cast<TUINT32 *>(rcm->getRawData());
			for (int i = 0; i < rin->getLy(); i++) {
				for (int j = 0; j < rin->getLx(); j++)
					*rowout++ = *rowin++; //Direct copy for now... :(
				rowin += rin->getWrap() - rin->getLx();
				rowout += rcm->getWrap() - rcm->getLx();
			}
		} else {
			TPixel32 *rowin = reinterpret_cast<TPixel32 *>(rin->getRawData());
			TUINT32 *rowout = reinterpret_cast<TUINT32 *>(rcm->getRawData());
			for (int i = 0; i < rin->getLy(); i++) {
				for (int j = 0; j < rin->getLx(); j++)
					*rowout++ = TPixelGR8::from(*rowin++).value;
				rowin += rin->getWrap() - rin->getLx();
				rowout += rcm->getWrap() - rcm->getLx();
			}
		}

		rin->unlock();
		rcm->unlock();
	} else {
		assert(TRaster32P(rin));
		preprocessColors(rcm, rin, m_parameters->m_colors);
	}

	//outImg->setDpi(outDpi.x, outDpi.y);
	CleanupPreprocessedImage cpi(m_parameters, TToonzImageP(rcm, rcm->getBounds()), toGr8);
	cpi.m_autocentered = true;

	TRaster32P rout = TRaster32P(rin->getSize());
	finalize(rout, &cpi);
	return rout;
}
示例#2
0
文件: fill.cpp 项目: luc--/opentoonz
TPoint nearestInk(const TRasterCM32P &r, const TPoint &p, int ray) {
  int i, j;
  TPixelCM32 *buf = (TPixelCM32 *)r->getRawData();

  for (j = std::max(p.y - ray, 0); j <= std::min(p.y + ray, r->getLy() - 1);
       j++)
    for (i = std::max(p.x - ray, 0); i <= std::min(p.x + ray, r->getLx() - 1);
         i++)
      if (!(buf + j * r->getWrap() + i)->isPurePaint()) return TPoint(i, j);

  return TPoint(-1, -1);
}
示例#3
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();
}
示例#4
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;
 }
示例#5
0
文件: blend.cpp 项目: luc--/opentoonz
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();
}
示例#6
0
文件: blend.cpp 项目: luc--/opentoonz
// 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...?
    }
  }
}
示例#7
0
文件: blend.cpp 项目: luc--/opentoonz
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();
}
示例#8
0
文件: blend.cpp 项目: luc--/opentoonz
// 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;
    }
}
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());