Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tools/stylepicker.h"
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tvectorrenderdata.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "toonz/dpiscale.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
#include "tregion.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
StylePicker::StylePicker(const TImageP &image)
Toshihiro Shimizu 890ddd
	: m_image(image), m_palette(image->getPalette())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
StylePicker::StylePicker(const TImageP &image, const TPaletteP &palette)
Toshihiro Shimizu 890ddd
	: m_image(image), m_palette(palette)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPoint StylePicker::getRasterPoint(const TPointD &p) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TToonzImageP ti = m_image) {
Toshihiro Shimizu 890ddd
		//DpiScale dpiScale(ti);
Toshihiro Shimizu 890ddd
		TDimension size = ti->getSize();
Toshihiro Shimizu 890ddd
		return TPoint(
Toshihiro Shimizu 890ddd
			tround(0.5 * size.lx + p.x),  ///dpiScale.getSx()),
Toshihiro Shimizu 890ddd
			tround(0.5 * size.ly + p.y)); ///dpiScale.getSy()));
Toshihiro Shimizu 890ddd
	} else if (TRasterImageP ri = m_image) {
Toshihiro Shimizu 890ddd
		//DpiScale dpiScale(ri);
Toshihiro Shimizu 890ddd
		TDimension size = ri->getRaster()->getSize();
Toshihiro Shimizu 890ddd
		return TPoint(
Toshihiro Shimizu 890ddd
			tround(0.5 * size.lx + p.x),  // /dpiScale.getSx()),
Toshihiro Shimizu 890ddd
			tround(0.5 * size.ly + p.y)); // /dpiScale.getSy()));
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		return TPoint(tround(p.x), tround(p.y));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
/*-- (StylePickerTool内で)LineとAreaを切り替えてPickできる。mode: 0=Area, 1=Line, 2=Line&Areas(default)  --*/
Toshihiro Shimizu 890ddd
int StylePicker::pickStyleId(const TPointD &pos, double radius2, int mode) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int styleId = 0;
Toshihiro Shimizu 890ddd
	if (TToonzImageP ti = m_image) {
Toshihiro Shimizu 890ddd
		TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
		TPoint point = getRasterPoint(pos);
Toshihiro Shimizu 890ddd
		if (!ras->getBounds().contains(point))
Toshihiro Shimizu 890ddd
			return -1;
Toshihiro Shimizu 890ddd
		TPixelCM32 col = ras->pixels(point.y)[point.x];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		switch (mode) {
Toshihiro Shimizu 890ddd
		case 0: //AREAS
Toshihiro Shimizu 890ddd
			styleId = col.getPaint();
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 1: //LINES
Toshihiro Shimizu 890ddd
			styleId = col.getInk();
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		case 2: //ALL (Line & Area)
Toshihiro Shimizu 890ddd
		default:
Toshihiro Shimizu 890ddd
			styleId = col.isPurePaint() ? col.getPaint() : col.getInk();
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else if (TRasterImageP ri = m_image) {
Toshihiro Shimizu 890ddd
		const TPalette *palette = m_palette.getPointer();
Toshihiro Shimizu 890ddd
		if (!palette)
Toshihiro Shimizu 890ddd
			return -1;
Toshihiro Shimizu 890ddd
		TRaster32P ras = ri->getRaster();
Toshihiro Shimizu 890ddd
		if (!ras)
Toshihiro Shimizu 890ddd
			return -1;
Toshihiro Shimizu 890ddd
		TPoint point = getRasterPoint(pos);
Toshihiro Shimizu 890ddd
		if (!ras->getBounds().contains(point))
Toshihiro Shimizu 890ddd
			return -1;
Toshihiro Shimizu 890ddd
		TPixel32 col = ras->pixels(point.y)[point.x];
Toshihiro Shimizu 890ddd
		styleId = palette->getClosestStyle(col);
Toshihiro Shimizu 890ddd
	} else if (TVectorImageP vi = m_image) {
Toshihiro Shimizu 890ddd
		// prima cerca lo stile della regione piu' vicina
Toshihiro Shimizu 890ddd
		TRegion *r = vi->getRegion(pos);
Toshihiro Shimizu 890ddd
		if (r)
Toshihiro Shimizu 890ddd
			styleId = r->getStyle();
Toshihiro Shimizu 890ddd
		// poi cerca quello della stroke, ma se prima aveva trovato una regione, richiede che
Toshihiro Shimizu 890ddd
		// il click sia proprio sopra la stroke, altrimenti cerca la stroke piu' vicina (max circa 10 pixel)
Toshihiro Shimizu 890ddd
		const double maxDist2 = (styleId == 0) ? 100.0 * radius2 : 0;
Toshihiro Shimizu 890ddd
		bool strokeFound;
Toshihiro Shimizu 890ddd
		double dist2, w, thick;
Toshihiro Shimizu 890ddd
		UINT index;
Toshihiro Shimizu 890ddd
		//!funzionerebbe ancora meglio con un getNearestStroke che considera
Toshihiro Shimizu 890ddd
		//la thickness, cioe' la min distance dalla outline e non dalla centerLine
Toshihiro Shimizu 890ddd
		strokeFound = vi->getNearestStroke(pos, w, index, dist2);
Toshihiro Shimizu 890ddd
		if (strokeFound) {
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi->getStroke(index);
Toshihiro Shimizu 890ddd
			thick = stroke->getThickPoint(w).thick;
Toshihiro Shimizu 890ddd
			if (dist2 - thick * thick < maxDist2) {
Toshihiro Shimizu 890ddd
				assert(stroke);
Toshihiro Shimizu 890ddd
				styleId = stroke->getStyle();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return styleId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
/*--- Toonz Raster LevelのToneを拾う。 ---*/
Toshihiro Shimizu 890ddd
int StylePicker::pickTone(const TPointD &pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TToonzImageP ti = m_image) {
Toshihiro Shimizu 890ddd
		TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
		if (!ras)
Toshihiro Shimizu 890ddd
			return -1;
Toshihiro Shimizu 890ddd
		TPoint point = getRasterPoint(pos);
Toshihiro Shimizu 890ddd
		if (!ras->getBounds().contains(point))
Toshihiro Shimizu 890ddd
			return -1;
Toshihiro Shimizu 890ddd
		TPixelCM32 col = ras->pixels(point.y)[point.x];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return col.getTone();
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPixel32 StylePicker::pickColor(const TPointD &pos, double radius2) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TToonzImageP ti = m_image;
Toshihiro Shimizu 890ddd
	TRasterImageP ri = m_image;
Toshihiro Shimizu 890ddd
	if (!!ri) // !!ti || !!ri)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TRasterP raster;
Toshihiro Shimizu 890ddd
		//if(ti)
Toshihiro Shimizu 890ddd
		//  raster = ti->getRGBM(true);
Toshihiro Shimizu 890ddd
		//else
Toshihiro Shimizu 890ddd
		raster = ri->getRaster();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPoint point = getRasterPoint(pos);
Toshihiro Shimizu 890ddd
		if (!raster->getBounds().contains(point))
Toshihiro Shimizu 890ddd
			return TPixel32::Transparent;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRaster32P raster32 = raster;
Toshihiro Shimizu 890ddd
		if (raster32)
Toshihiro Shimizu 890ddd
			return raster32->pixels(point.y)[point.x];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRasterGR8P rasterGR8 = raster;
Toshihiro Shimizu 890ddd
		if (rasterGR8)
Toshihiro Shimizu 890ddd
			return toPixel32(rasterGR8->pixels(point.y)[point.x]);
Toshihiro Shimizu 890ddd
	} else if (TVectorImageP vi = m_image) {
Toshihiro Shimizu 890ddd
		const TPalette *palette = m_palette.getPointer();
Toshihiro Shimizu 890ddd
		if (!palette)
Toshihiro Shimizu 890ddd
			return TPixel32::Transparent;
Toshihiro Shimizu 890ddd
		int styleId = pickStyleId(pos, radius2);
Toshihiro Shimizu 890ddd
		if (0 <= styleId && styleId < palette->getStyleCount())
Toshihiro Shimizu 890ddd
			return palette->getStyle(styleId)->getAverageColor();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TPixel32::Transparent;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPixel32 getAverageColor(const TRect &rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	GLenum fmt =
Toshihiro Shimizu 890ddd
#ifdef TNZ_MACHINE_CHANNEL_ORDER_BGRM
Toshihiro Shimizu 890ddd
		GL_RGBA;
Toshihiro Shimizu 890ddd
#elif TNZ_MACHINE_CHANNEL_ORDER_MBGR
Toshihiro Shimizu 890ddd
		GL_ABGR_EXT;
Toshihiro Shimizu 890ddd
#elif TNZ_MACHINE_CHANNEL_ORDER_RGBM
Toshihiro Shimizu 890ddd
		GL_RGBA;
Toshihiro Shimizu 890ddd
#elif TNZ_MACHINE_CHANNEL_ORDER_MRGB
Toshihiro Shimizu 890ddd
		GL_BGRA;
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
//   Error  PLATFORM NOT SUPPORTED
Campbell Barton 42d601
#error	"unknown channel order!"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	UINT r = 0, g = 0, b = 0, m = 0;
Shinya Kitaoka 3bfa54
	std::vector<tpixel32> buffer(rect.getLx() * rect.getLy());</tpixel32>
Toshihiro Shimizu 890ddd
	glReadPixels(rect.x0, rect.y0, rect.getLx(), rect.getLy(), fmt, GL_UNSIGNED_BYTE, &buffer[0]);
Toshihiro Shimizu 890ddd
	int size = rect.getLx() * rect.getLy();
Toshihiro Shimizu 890ddd
	for (int i = 0; i < size; i++) {
Toshihiro Shimizu 890ddd
		r += buffer[i].r;
Toshihiro Shimizu 890ddd
		g += buffer[i].g;
Toshihiro Shimizu 890ddd
		b += buffer[i].b;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TPixel32(b / size, g / size, r / size, 255);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPixel32 getAverageColor(TStroke *stroke)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	GLenum fmt =
Toshihiro Shimizu 890ddd
#ifdef TNZ_MACHINE_CHANNEL_ORDER_BGRM
Toshihiro Shimizu 890ddd
		GL_RGBA;
Toshihiro Shimizu 890ddd
#elif TNZ_MACHINE_CHANNEL_ORDER_MBGR
Toshihiro Shimizu 890ddd
		GL_ABGR_EXT;
Toshihiro Shimizu 890ddd
#elif TNZ_MACHINE_CHANNEL_ORDER_RGBM
Toshihiro Shimizu 890ddd
		GL_RGBA;
Toshihiro Shimizu 890ddd
#elif TNZ_MACHINE_CHANNEL_ORDER_MRGB
Toshihiro Shimizu 890ddd
		GL_BGRA;
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
//   Error  PLATFORM NOT SUPPORTED
Campbell Barton 42d601
#error	"unknown channel order"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//leggo il buffer e mi prendo i pixels
Toshihiro Shimizu 890ddd
	UINT r = 0, g = 0, b = 0, m = 0;
Toshihiro Shimizu 890ddd
	TRect rect = convert(stroke->getBBox());
Shinya Kitaoka 3bfa54
	std::vector<tpixel32> buffer(rect.getLx() * rect.getLy());</tpixel32>
Toshihiro Shimizu 890ddd
	glReadPixels(rect.x0, rect.y0, rect.getLx(), rect.getLy(), fmt, GL_UNSIGNED_BYTE, &buffer[0]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//calcolo le regioni dello stroke
Toshihiro Shimizu 890ddd
	TVectorImage aux;
Toshihiro Shimizu 890ddd
	aux.addStroke(stroke);
Toshihiro Shimizu 890ddd
	aux.transform(TTranslation(convert(-rect.getP00())));
Toshihiro Shimizu 890ddd
	aux.findRegions();
Toshihiro Shimizu 890ddd
	int regionCount = aux.getRegionCount();
Toshihiro Shimizu 890ddd
	int size = 0, lx = rect.getLx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int j = 0; j < regionCount; j++) {
Toshihiro Shimizu 890ddd
		TRegion *reg = aux.getRegion(j);
Toshihiro Shimizu 890ddd
		TRect regRect = convert(reg->getBBox());
Toshihiro Shimizu 890ddd
		for (int y = regRect.y0; y < regRect.y1; y++) {
Shinya Kitaoka 3bfa54
			std::vector<double> intersections;</double>
Toshihiro Shimizu 890ddd
			reg->computeScanlineIntersections(y, intersections);
Toshihiro Shimizu 890ddd
			assert(!(intersections.size() & 0x1));
Toshihiro Shimizu 890ddd
			for (UINT i = 0; i < intersections.size(); i += 2) {
Toshihiro Shimizu 890ddd
				if (intersections[i] == intersections[i + 1])
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				int firstInters = (int)intersections[i];
Toshihiro Shimizu 890ddd
				int secondInters = (int)intersections[i + 1];
Toshihiro Shimizu 890ddd
				for (int x = firstInters + 1; x < secondInters - 1; x++) {
Toshihiro Shimizu 890ddd
					r += buffer[y * lx + x].r;
Toshihiro Shimizu 890ddd
					g += buffer[y * lx + x].g;
Toshihiro Shimizu 890ddd
					b += buffer[y * lx + x].b;
Toshihiro Shimizu 890ddd
					size++;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (size != 0)
Toshihiro Shimizu 890ddd
		return TPixel32(b / size, g / size, r / size, 255);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return TPixel32(buffer[0].b, buffer[0].g, buffer[0].r, 255);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namspace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPixel32 StylePicker::pickColor(const TRectD &area) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//TRectD rect=area.enlarge(-1,-1);
Toshihiro Shimizu 890ddd
	return getAverageColor(convert(area));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPixel32 StylePicker::pickColor(TStroke *stroke) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return getAverageColor(stroke);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------