Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/toonzimageutils.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tvectorrenderdata.h"
Toshihiro Shimizu 890ddd
#include "tvectorgl.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "toonz/ttileset.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcenterlinevectorizer.h"
Toshihiro Shimizu 890ddd
#include "tregion.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "ttzpimagefx.h"
Toshihiro Shimizu 890ddd
#include "tlevel_io.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tsimplecolorstyles.h"
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const int BackgroundStyle = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRect rasterizeStroke(TOfflineGL *&gl, const TRect &rasBounds, TStroke *stroke,
Toshihiro Shimizu 890ddd
					  TPalette *palette, const TRectD &clip, bool doAntialias)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRectD bbox = clip * stroke->getBBox();
Toshihiro Shimizu 890ddd
	TRect rect = convert(bbox).enlarge(1) * rasBounds;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (rect.getLx() <= 0 || rect.getLy() <= 0)
Toshihiro Shimizu 890ddd
		return TRect();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	gl = new TOfflineGL(rect.getSize());
Toshihiro Shimizu 890ddd
	gl->makeCurrent();
Toshihiro Shimizu 890ddd
	gl->clear(TPixel32::White);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPaletteP plt = palette->clone();
Toshihiro Shimizu 890ddd
	int styleId = stroke->getStyle();
Toshihiro Shimizu 890ddd
	TColorStyleP style = plt->getStyle(styleId);
Toshihiro Shimizu 890ddd
	assert(style);
Toshihiro Shimizu 890ddd
	style->setMainColor(TPixel32::Black);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTranslation affine(-convert(rect.getP00()));
Toshihiro Shimizu 890ddd
	TVectorRenderData rd(affine, gl->getBounds(), plt.getPointer(), 0, false, doAntialias);
Toshihiro Shimizu 890ddd
	tglDraw(rd, stroke);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glFinish();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return rect;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRect rasterizeStroke(TOfflineGL *&gl, TRect rasBounds, TStroke *stroke, TRectD clip, bool filled = false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TDimension d = rasBounds.getSize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD offset(d.lx * 0.5, d.ly * 0.5);
Toshihiro Shimizu 890ddd
	TTranslation offsetMatrix(offset);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD strokeBBox = stroke->getBBox().enlarge(2);
Toshihiro Shimizu 890ddd
	if (!clip.isEmpty())
Toshihiro Shimizu 890ddd
		strokeBBox = offsetMatrix * (strokeBBox * clip);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		strokeBBox = offsetMatrix * strokeBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRect rect = ToonzImageUtils::convertWorldToRaster(strokeBBox, 0) * rasBounds;
Toshihiro Shimizu 890ddd
	if (!rect.isEmpty()) {
Toshihiro Shimizu 890ddd
		gl = new TOfflineGL(rect.getSize());
Toshihiro Shimizu 890ddd
		gl->makeCurrent();
Toshihiro Shimizu 890ddd
		glClearColor(1, 1, 1, 1);
Toshihiro Shimizu 890ddd
		glClear(GL_COLOR_BUFFER_BIT);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPalette *palette = new TPalette();
Toshihiro Shimizu 890ddd
		TTranslation affine(-strokeBBox.getP00() + offset);
Toshihiro Shimizu 890ddd
		TVectorRenderData rd(affine, gl->getBounds(), palette, 0, false, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int oldStyle = stroke->getStyle();
Toshihiro Shimizu 890ddd
		stroke->setStyle(1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (filled) {
Toshihiro Shimizu 890ddd
			TVectorImage vi;
Toshihiro Shimizu 890ddd
			vi.addStroke(new TStroke(*stroke));
Toshihiro Shimizu 890ddd
			vi.findRegions();
Toshihiro Shimizu 890ddd
			vi.selectFill(vi.getBBox().enlarge(2), 0, 1, false, true, false);
Toshihiro Shimizu 890ddd
			tglDraw(rd, &vi);
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			tglDraw(rd, stroke);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete palette;
Toshihiro Shimizu 890ddd
		stroke->setStyle(oldStyle);
Toshihiro Shimizu 890ddd
		glFinish();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return rect;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRect rasterizeRegion(TOfflineGL *&gl, TRect rasBounds, TRegion *region, TRectD clip)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRectD regionBBox = region->getBBox();
Toshihiro Shimizu 890ddd
	if (!clip.isEmpty())
Toshihiro Shimizu 890ddd
		regionBBox = regionBBox * clip;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRect rect = convert(regionBBox) * rasBounds;
Toshihiro Shimizu 890ddd
	if (!rect.isEmpty()) {
Toshihiro Shimizu 890ddd
		gl = new TOfflineGL(rect.getSize());
Toshihiro Shimizu 890ddd
		gl->makeCurrent();
Toshihiro Shimizu 890ddd
		gl->clear(TPixel32::White);
Toshihiro Shimizu 890ddd
		glPushAttrib(GL_ALL_ATTRIB_BITS);
Toshihiro Shimizu 890ddd
		glEnable(GL_ALPHA_TEST);
Toshihiro Shimizu 890ddd
		glAlphaFunc(GL_GREATER, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPalette *palette = new TPalette();
Toshihiro Shimizu 890ddd
		TTranslation affine(-convert(rect.getP00()));
Toshihiro Shimizu 890ddd
		TVectorRenderData rd(affine, gl->getBounds(), palette, 0, true, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int oldStyle = region->getStyle();
Toshihiro Shimizu 890ddd
		region->setStyle(1);
Toshihiro Shimizu 890ddd
		tglDraw(rd, region);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glDisable(GL_ALPHA_TEST);
Toshihiro Shimizu 890ddd
		glPopAttrib();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		region->setStyle(oldStyle);
Toshihiro Shimizu 890ddd
		glFinish();
Toshihiro Shimizu 890ddd
		delete palette;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return rect;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void fastAddPaintRegion(const TToonzImageP &ti, TRegion *region,
Toshihiro Shimizu 890ddd
						int newPaintId, int maxStyleId, TRectD clip = TRectD())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
	TOfflineGL *gl;
Toshihiro Shimizu 890ddd
	TRect rect = rasterizeRegion(gl, ras->getBounds(), region, clip);
Toshihiro Shimizu 890ddd
	if (rect.isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P glRas = gl->getRaster();
Toshihiro Shimizu 890ddd
	assert(TPixelCM32::getMaxTone() == 255);
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	glRas->lock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int y = rect.y0; y <= rect.y1; y++) {
Toshihiro Shimizu 890ddd
		TPixel32 *inPix = glRas->pixels(y - rect.y0);
Toshihiro Shimizu 890ddd
		TPixelCM32 *outPix = ras->pixels(y) + rect.x0;
Toshihiro Shimizu 890ddd
		TPixel32 *inEndPix = inPix + rect.x1 - rect.x0 + 1;
Toshihiro Shimizu 890ddd
		for (; inPix < inEndPix; ++outPix, ++inPix)
Toshihiro Shimizu 890ddd
			if (inPix->r < 128) {
Toshihiro Shimizu 890ddd
				outPix->setPaint(newPaintId);
Toshihiro Shimizu 890ddd
				outPix->setTone(255);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
	glRas->unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	delete gl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRegion *subregion;
Toshihiro Shimizu 890ddd
	UINT i = 0;
Toshihiro Shimizu 890ddd
	for (; i < region->getSubregionCount(); ++i) {
Toshihiro Shimizu 890ddd
		subregion = region->getSubregion(i);
Toshihiro Shimizu 890ddd
		fastAddPaintRegion(ti, subregion, tmin(maxStyleId, subregion->getStyle()), maxStyleId);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRect ToonzImageUtils::convertWorldToRaster(const TRectD area, const TToonzImageP ti)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (area.isEmpty())
Toshihiro Shimizu 890ddd
		return TRect();
Toshihiro Shimizu 890ddd
	if (!ti || !ti->getRaster())
Toshihiro Shimizu 890ddd
		return TRect(tfloor(area.x0), tfloor(area.y0), tfloor(area.x1) - 1, tfloor(area.y1) - 1);
Toshihiro Shimizu 890ddd
	TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
	TRectD rect(area + ras->getCenterD());
Toshihiro Shimizu 890ddd
	return TRect(tfloor(rect.x0), tfloor(rect.y0), tceil(rect.x1) - 1, tceil(rect.y1) - 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRectD ToonzImageUtils::convertRasterToWorld(const TRect area, const TToonzImageP ti)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (area.isEmpty())
Toshihiro Shimizu 890ddd
		return TRectD();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD rect(area.x0, area.y0, area.x1 + 1, area.y1 + 1);
Toshihiro Shimizu 890ddd
	if (ti && ti->getRaster())
Toshihiro Shimizu 890ddd
		rect = rect - ti->getRaster()->getCenterD();
Toshihiro Shimizu 890ddd
	return rect;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//clip in coordinate world (cioe' della stroke)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//overlaying inks, blend inks always "lose" on normal inks
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRect fastAddInkStroke(const TToonzImageP &ti, TStroke *stroke, int inkId, bool selective,
Toshihiro Shimizu 890ddd
					   bool filled, TRectD clip, bool doAntialiasing = true, const set<int> &blendInks = set<int>())</int></int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
	TOfflineGL *gl = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRect rectRender = rasterizeStroke(gl, ras->getBounds(), stroke, ti->getPalette(), clip, doAntialiasing);
Toshihiro Shimizu 890ddd
	if (!gl)
Toshihiro Shimizu 890ddd
		return TRect();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P glRas = gl->getRaster();
Toshihiro Shimizu 890ddd
	TRasterCM32P outRas = ras->extract(rectRender);
Toshihiro Shimizu 890ddd
	assert(glRas->getSize() == outRas->getSize());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(TPixelCM32::getMaxTone() == 255);
Toshihiro Shimizu 890ddd
	outRas->lock();
Toshihiro Shimizu 890ddd
	glRas->lock();
Toshihiro Shimizu 890ddd
	bool isBlendInkUp = (blendInks.find(inkId) != blendInks.end());
Toshihiro Shimizu 890ddd
	for (int y = 0; y < outRas->getLy(); ++y) {
Toshihiro Shimizu 890ddd
		TPixel32 *inPix = glRas->pixels(y);
Toshihiro Shimizu 890ddd
		TPixelCM32 *outPix = outRas->pixels(y);
Toshihiro Shimizu 890ddd
		for (int x = 0; x < outRas->getLx(); ++outPix, ++inPix, ++x) {
Toshihiro Shimizu 890ddd
			int upTone = inPix->r;
Toshihiro Shimizu 890ddd
			int dnTone = outPix->getTone();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (doAntialiasing) {
Toshihiro Shimizu 890ddd
				//overlaying inks, blend inks always "lose" on normal inks
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				bool isBlendInkDn = (blendInks.find(outPix->getInk()) != blendInks.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (isBlendInkUp && !isBlendInkDn && dnTone < 255)
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (isBlendInkDn && !isBlendInkUp && upTone < 255) {
Toshihiro Shimizu 890ddd
					*outPix = TPixelCM32(inkId, outPix->getPaint(), upTone);
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//The upper pixel replaces the lower one, *if*
Toshihiro Shimizu 890ddd
				//  a) It's more opaque
Toshihiro Shimizu 890ddd
				//  b) If the ink id id not the same, ink is not completely transparent
Toshihiro Shimizu 890ddd
				//  c)  ...
Toshihiro Shimizu 890ddd
				if ((upTone <= dnTone) &&
Toshihiro Shimizu 890ddd
					((outPix->getInk() == inkId) || (upTone != 255)) &&
Toshihiro Shimizu 890ddd
					(!selective || !outPix->isPureInk()))
Toshihiro Shimizu 890ddd
					*outPix = TPixelCM32(inkId, outPix->getPaint(), upTone);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				if (!selective || !outPix->isPureInk()) {
Toshihiro Shimizu 890ddd
					//if(upTone<=192 && upTone<=dnTone)
Toshihiro Shimizu 890ddd
					if (upTone == 0)
Toshihiro Shimizu 890ddd
						*outPix = TPixelCM32(inkId, outPix->getPaint(), 0);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	outRas->unlock();
Toshihiro Shimizu 890ddd
	glRas->unlock();
Toshihiro Shimizu 890ddd
	delete gl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return rectRender;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//clip in coordinate world (cioe' della stroke)
Toshihiro Shimizu 890ddd
TRect ToonzImageUtils::addInkStroke(const TToonzImageP &ti, TStroke *stroke, int inkId, bool selective,
Toshihiro Shimizu 890ddd
									bool filled, TRectD clip, bool doAntialiasing)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TStroke *s = new TStroke(*stroke);
Toshihiro Shimizu 890ddd
	TPoint tiCenter = ti->getRaster()->getCenter();
Toshihiro Shimizu 890ddd
	s->transform(TTranslation(tiCenter.x, tiCenter.y));
Toshihiro Shimizu 890ddd
	TRect rect = fastAddInkStroke(ti, s, inkId, selective, filled, clip, doAntialiasing);
Toshihiro Shimizu 890ddd
	rect -= tiCenter;
Toshihiro Shimizu 890ddd
	return rect;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRect ToonzImageUtils::changeColorStroke(const TToonzImageP &ti, const ChangeColorStrokeSettings &settings)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!settings.changeInk && !settings.changePaint)
Toshihiro Shimizu 890ddd
		return TRect();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
	TOfflineGL *gl;
Toshihiro Shimizu 890ddd
	TRect rect = rasterizeStroke(gl, ras->getBounds(), settings.stroke, settings.clip);
Toshihiro Shimizu 890ddd
	if (rect.isEmpty()) {
Toshihiro Shimizu 890ddd
		return rect;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TRaster32P glRas = gl->getRaster();
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	glRas->lock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int y = rect.y0; y <= rect.y1; ++y) {
Toshihiro Shimizu 890ddd
		TPixel32 *inPix = glRas->pixels(y - rect.y0);
Toshihiro Shimizu 890ddd
		TPixelCM32 *outPix = ras->pixels(y) + rect.x0;
Toshihiro Shimizu 890ddd
		TPixel32 *inEndPix = inPix + rect.x1 - rect.x0 + 1;
Toshihiro Shimizu 890ddd
		for (; inPix < inEndPix; ++outPix, ++inPix) {
Toshihiro Shimizu 890ddd
			if (inPix->r < 128 && settings.changeInk && !outPix->isPurePaint())
Toshihiro Shimizu 890ddd
				outPix->setInk(settings.colorId);
Toshihiro Shimizu 890ddd
			if (inPix->r < 128 && settings.changePaint &&
Toshihiro Shimizu 890ddd
				(settings.maskPaintId == -1 || outPix->getPaint() == settings.maskPaintId))
Toshihiro Shimizu 890ddd
				outPix->setPaint(settings.colorId);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	delete gl;
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
	glRas->unlock();
Toshihiro Shimizu 890ddd
	return rect;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TRect ToonzImageUtils::eraseRect(const TToonzImageP &ti, const TRectD &area, int maskId, bool onInk, bool onPaint)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(onInk || onPaint);
Toshihiro Shimizu 890ddd
	TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
	TRect rect = convertWorldToRaster(area, ti) * ras->getBounds();
Toshihiro Shimizu 890ddd
	if (rect.isEmpty())
Toshihiro Shimizu 890ddd
		return rect;
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int y = rect.y0; y <= rect.y1; y++) {
Toshihiro Shimizu 890ddd
		TPixelCM32 *pix = ras->pixels(y) + rect.x0;
Toshihiro Shimizu 890ddd
		TPixelCM32 *endPix = ras->pixels(y) + rect.x1 + 1;
Toshihiro Shimizu 890ddd
		for (; pix < endPix; ++pix) {
Toshihiro Shimizu 890ddd
			if (onPaint && (maskId == -1 || maskId == pix->getPaint()))
Toshihiro Shimizu 890ddd
				pix->setPaint(BackgroundStyle);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (onInk && (maskId == -1 || maskId == pix->getInk()))
Toshihiro Shimizu 890ddd
				*pix = TPixelCM32(BackgroundStyle, pix->getPaint(), TPixelCM32::getMaxTone());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
	return rect;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
std::vector<trect> ToonzImageUtils::paste(const TToonzImageP &ti, const TTileSetCM32 *tileSet)</trect>
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 3bfa54
	std::vector<trect> rects;</trect>
Toshihiro Shimizu 890ddd
	TRasterCM32P raster = ti->getRaster();
Toshihiro Shimizu 890ddd
	//for(int i=0;i<tileset->getTileCount();i++)</tileset->
Toshihiro Shimizu 890ddd
	for (int i = tileSet->getTileCount() - 1; i >= 0; i--) {
Toshihiro Shimizu 890ddd
		const TTileSetCM32::Tile *tile = tileSet->getTile(i);
Toshihiro Shimizu 890ddd
		TRasterCM32P rasCM32;
Toshihiro Shimizu 890ddd
		tile->getRaster(rasCM32);
Toshihiro Shimizu 890ddd
		assert(!!rasCM32);
Toshihiro Shimizu 890ddd
		raster->copy(rasCM32, tile->m_rasterBounds.getP00());
Toshihiro Shimizu 890ddd
		rects.push_back(tile->m_rasterBounds);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return rects;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// DA RIFARE
Toshihiro Shimizu 890ddd
// e' lenta da far schifo
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Converts a TVectorImage into a TToonzImage. The input vector image
Toshihiro Shimizu 890ddd
//!is transformed through the passed affine \b aff, and put into a
Toshihiro Shimizu 890ddd
//!TToonzImage strictly covering the bounding box of the transformed
Toshihiro Shimizu 890ddd
//!vector image. The output image has its lower-left position in the
Toshihiro Shimizu 890ddd
//!world reference specified by the \b pos parameter, which is granted to
Toshihiro Shimizu 890ddd
//!be an integer displacement of the passed value. Additional parameters
Toshihiro Shimizu 890ddd
//!include an integer \b enlarge by which the output image is enlarged with
Toshihiro Shimizu 890ddd
//!respect to the transformed image's bbox, and the bool \b transformThickness
Toshihiro Shimizu 890ddd
//!to specify whether the transformation should involve strokes' thickensses
Toshihiro Shimizu 890ddd
//!or not.
Toshihiro Shimizu 890ddd
TToonzImageP ToonzImageUtils::vectorToToonzImage(
Toshihiro Shimizu 890ddd
	const TVectorImageP &vimage, const TAffine &aff, TPalette *palette,
Toshihiro Shimizu 890ddd
	const TPointD &outputPos, const TDimension &outputSize,
Shinya Kitaoka 3bfa54
	const std::vector<trasterfxrenderdatap> *fxs, bool transformThickness)</trasterfxrenderdatap>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!vimage || !palette)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Transform the vector image through aff
Toshihiro Shimizu 890ddd
	TVectorImageP vi = vimage->clone();
Toshihiro Shimizu 890ddd
	vi->transform(aff, transformThickness);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Allocate the output ToonzImage
Toshihiro Shimizu 890ddd
	TRasterCM32P raster(outputSize.lx, outputSize.ly);
Toshihiro Shimizu 890ddd
	raster->clear();
Toshihiro Shimizu 890ddd
	TToonzImageP ti(raster, raster->getBounds());
Toshihiro Shimizu 890ddd
	ti->setPalette(palette->clone());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Shift outputPos to the origin
Toshihiro Shimizu 890ddd
	vi->transform(TTranslation(-outputPos));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int strokeCount = vi->getStrokeCount();
Shinya Kitaoka 3bfa54
	std::vector<int> strokeIndex(strokeCount);</int>
Shinya Kitaoka 3bfa54
	std::vector<tstroke *=""> strokes(strokeCount);</tstroke>
Toshihiro Shimizu 890ddd
	int maxStyleId = palette->getStyleCount() - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < strokeCount; ++i) {
Toshihiro Shimizu 890ddd
		strokeIndex[i] = i;
Toshihiro Shimizu 890ddd
		strokes[i] = vi->getStroke(i);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	vi->notifyChangedStrokes(strokeIndex, strokes);
Toshihiro Shimizu 890ddd
	int regionCount = vi->getRegionCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//In such reference, the clip for rendering strokes is the output size
Toshihiro Shimizu 890ddd
	TRectD clip(TDimensionD(outputSize.lx, outputSize.ly));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	set<int> colors;</int>
Toshihiro Shimizu 890ddd
	if (fxs) {
Toshihiro Shimizu 890ddd
		for (i = 0; i < (int)fxs->size(); i++) {
Toshihiro Shimizu 890ddd
			SandorFxRenderData *sandorData = dynamic_cast<sandorfxrenderdata *="">((*fxs)[i].getPointer());</sandorfxrenderdata>
Toshihiro Shimizu 890ddd
			if (sandorData && sandorData->m_type == BlendTz) {
Shinya Kitaoka 3bfa54
				std::string indexes = toString(sandorData->m_blendParams.m_colorIndex);
Shinya Kitaoka 3bfa54
				std::vector<std::string> items;</std::string>
Toshihiro Shimizu 890ddd
				parseIndexes(indexes, items);
Toshihiro Shimizu 890ddd
				PaletteFilterFxRenderData paletteFilterData;
Toshihiro Shimizu 890ddd
				insertIndexes(items, &paletteFilterData);
Toshihiro Shimizu 890ddd
				colors.insert(paletteFilterData.m_colors.begin(), paletteFilterData.m_colors.end());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int k, l;
Toshihiro Shimizu 890ddd
	for (i = 0; i < strokeCount;) {
Toshihiro Shimizu 890ddd
		//Draw all regions which have the same group.
Toshihiro Shimizu 890ddd
		for (k = 0; k < regionCount; ++k)
Toshihiro Shimizu 890ddd
			if (vi->areDifferentGroup(i, false, k, true) == -1) {
Toshihiro Shimizu 890ddd
				TRegion *region = vi->getRegion(k);
Toshihiro Shimizu 890ddd
				fastAddPaintRegion(ti, region, tmin(maxStyleId, region->getStyle()), maxStyleId);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Find the first stroke which does not belong to the group
Toshihiro Shimizu 890ddd
		for (k = i; k < strokeCount && vi->areDifferentGroup(i, false, k, false) == -1; ++k)
Toshihiro Shimizu 890ddd
			;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Draw all found strokes
Toshihiro Shimizu 890ddd
		for (l = i; l < k; ++l) {
Toshihiro Shimizu 890ddd
			TStroke *stroke = vi->getStroke(l);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			bool visible = false;
Toshihiro Shimizu 890ddd
			int styleId = stroke->getStyle();
Toshihiro Shimizu 890ddd
			TColorStyleP style = palette->getStyle(styleId);
Toshihiro Shimizu 890ddd
			assert(style);
Toshihiro Shimizu 890ddd
			int colorCount = style->getColorParamCount();
Toshihiro Shimizu 890ddd
			if (colorCount == 0)
Toshihiro Shimizu 890ddd
				visible = true;
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				visible = false;
Toshihiro Shimizu 890ddd
				for (int j = 0; j < style->getColorParamCount() && !visible; j++) {
Toshihiro Shimizu 890ddd
					TPixel32 color = style->getColorParamValue(j);
Toshihiro Shimizu 890ddd
					if (color.m != 0)
Toshihiro Shimizu 890ddd
						visible = true;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (visible)
Toshihiro Shimizu 890ddd
				fastAddInkStroke(ti, stroke, tmin(maxStyleId, stroke->getStyle()), false, false, clip, true, colors);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		i = k;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return ti;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPalette *ToonzImageUtils::loadTzPalette(const TFilePath &pltFile)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TImageP pltImg;
Toshihiro Shimizu 890ddd
	TImageReader loader(pltFile);
Toshihiro Shimizu 890ddd
	pltImg = loader.load();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterImageP pltRasImg(pltImg);
Toshihiro Shimizu 890ddd
	if (!pltRasImg)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRaster32P rasPlt = pltRasImg->getRaster();
Toshihiro Shimizu 890ddd
	if (!rasPlt)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
	std::map<int, std::pair<std::string,="" std::string="">> pltColorNames;</int,>
Shinya Kitaoka 3bfa54
	std::map<int, std::pair<std::string,="" std::string="">>::iterator it;</int,>
Toshihiro Shimizu 890ddd
	loader.getTzpPaletteColorNames(pltColorNames);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPalette *palette = new TPalette();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const int offset = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(rasPlt->getLy() == 2);
Toshihiro Shimizu 890ddd
	rasPlt->lock();
Toshihiro Shimizu 890ddd
	TPixel32 *pixelRow = rasPlt->pixels(0);
Toshihiro Shimizu 890ddd
	int x = 0;
Toshihiro Shimizu 890ddd
	int count = palette->getStyleCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (; x < rasPlt->getLx(); ++x) {
Toshihiro Shimizu 890ddd
		TSolidColorStyle *style = new TSolidColorStyle(pixelRow[x]);
Toshihiro Shimizu 890ddd
		if ((it = pltColorNames.find(x)) != pltColorNames.end()) {
Shinya Kitaoka 3bfa54
			std::string styleName = it->second.second;
Toshihiro Shimizu 890ddd
			style->setName(toWideString(styleName));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (x < count)
Toshihiro Shimizu 890ddd
			palette->setStyle(x, style);
Toshihiro Shimizu 890ddd
		//palette->setStyle(x, pixelRow[x]);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			palette->addStyle(style);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// aggiungo solo i colori usati (salvo il BG)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPalette::Page *page = palette->getPage(0);
Toshihiro Shimizu 890ddd
	// nella pagina c'e' gia' lo sfondo e il colore 1:
Toshihiro Shimizu 890ddd
	// tolgo quest'ultimo
Toshihiro Shimizu 890ddd
	page->removeStyle(1);
Toshihiro Shimizu 890ddd
	// aggiungo gli altri
Shinya Kitaoka 3bfa54
	std::map<std::wstring, int=""> pages;</std::wstring,>
Shinya Kitaoka 3bfa54
	std::map<std::wstring, int="">::iterator itpage;</std::wstring,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pixelRow = rasPlt->pixels(1);
Toshihiro Shimizu 890ddd
	for (x = 0; x < rasPlt->getLx(); ++x) {
Toshihiro Shimizu 890ddd
		if ((it = pltColorNames.find(x)) != pltColorNames.end()) {
Shinya Kitaoka 3bfa54
			std::wstring pageName;
Toshihiro Shimizu 890ddd
			pageName = toWideString(it->second.first);
Toshihiro Shimizu 890ddd
			if (x == 0) {
Toshihiro Shimizu 890ddd
				page = palette->getPage(0);
Toshihiro Shimizu 890ddd
				page->setName(pageName);
Toshihiro Shimizu 890ddd
				pages[pageName] = 0;
Toshihiro Shimizu 890ddd
			} else if ((itpage = pages.find(pageName)) != pages.end())
Toshihiro Shimizu 890ddd
				page = palette->getPage(itpage->second);
Toshihiro Shimizu 890ddd
			else {
Toshihiro Shimizu 890ddd
				page = palette->addPage(pageName);
Toshihiro Shimizu 890ddd
				pages[pageName] = page->getIndex();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			page = palette->getPage(0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (pixelRow[x].r == 255)
Toshihiro Shimizu 890ddd
			page->addStyle(offset + x);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	rasPlt->unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return palette;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ToonzImageUtils::getUsedStyles(std::set<int> &styles, const TToonzImageP &ti)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
	if (!ras)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	int lx = ras->getLx();
Toshihiro Shimizu 890ddd
	int ly = ras->getLy();
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	for (int y = 0; y < ly; y++) {
Toshihiro Shimizu 890ddd
		TPixelCM32 *pix = ras->pixels(y);
Toshihiro Shimizu 890ddd
		TPixelCM32 *endPix = pix + lx;
Toshihiro Shimizu 890ddd
		while (pix < endPix) {
Toshihiro Shimizu 890ddd
			styles.insert(pix->getInk());
Toshihiro Shimizu 890ddd
			styles.insert(pix->getPaint());
Toshihiro Shimizu 890ddd
			++pix;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ToonzImageUtils::scrambleStyles(const TToonzImageP &ti, std::map<int, int=""> styleTable)</int,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRasterCM32P ras = ti->getRaster();
Toshihiro Shimizu 890ddd
	if (!ras)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	if (styleTable.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	std::map<int, int="">::iterator it;</int,>
Toshihiro Shimizu 890ddd
	std::vector<int> lut(4096, -1);</int>
Toshihiro Shimizu 890ddd
	bool isIdentity = true;
Toshihiro Shimizu 890ddd
	for (it = styleTable.begin(); it != styleTable.end(); ++it) {
Toshihiro Shimizu 890ddd
		int j = it->first, k = it->second;
Toshihiro Shimizu 890ddd
		assert(j >= 0);
Toshihiro Shimizu 890ddd
		assert(j < 1000000);
Toshihiro Shimizu 890ddd
		if (j >= (int)lut.size())
Toshihiro Shimizu 890ddd
			lut.resize(j + 1, -1);
Toshihiro Shimizu 890ddd
		lut[j] = k;
Toshihiro Shimizu 890ddd
		if (j != k)
Toshihiro Shimizu 890ddd
			isIdentity = false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (isIdentity)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m = lut.size();
Toshihiro Shimizu 890ddd
	int lx = ras->getLx();
Toshihiro Shimizu 890ddd
	int ly = ras->getLy();
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	for (int y = 0; y < ly; y++) {
Toshihiro Shimizu 890ddd
		TPixelCM32 *pix = ras->pixels(y);
Toshihiro Shimizu 890ddd
		TPixelCM32 *endPix = pix + lx;
Toshihiro Shimizu 890ddd
		while (pix < endPix) {
Toshihiro Shimizu 890ddd
			int ink = pix->getInk();
Toshihiro Shimizu 890ddd
			if (0 <= ink && ink < m && lut[ink] >= 0)
Toshihiro Shimizu 890ddd
				ink = lut[ink];
Toshihiro Shimizu 890ddd
			int paint = pix->getPaint();
Toshihiro Shimizu 890ddd
			if (0 <= paint && paint < m && lut[paint] >= 0)
Toshihiro Shimizu 890ddd
				paint = lut[paint];
Toshihiro Shimizu 890ddd
			if (ink != pix->getInk() || paint != pix->getPaint()) {
Toshihiro Shimizu 890ddd
				*pix = TPixelCM32(ink, paint, pix->getTone());
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			++pix;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef LEVO
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ToonzImageUtils::convertToTlv(const TFilePath &levelPathIn)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		TFilePath levelPathOut = levelPathIn.getParentDir() + TFilePath(levelPathIn.getWideName() + L".tlv");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TLevelReaderP lr(levelPathIn);
Toshihiro Shimizu 890ddd
		TLevelP level = lr->loadInfo();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TLevelWriterP lw(levelPathOut, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPalette *plt = new TPalette();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TLevel::Iterator it = level->begin();
Toshihiro Shimizu 890ddd
		TLevel::Iterator end = level->end();
Toshihiro Shimizu 890ddd
		for (; it != level->end(); ++it) {
Toshihiro Shimizu 890ddd
			try {
Toshihiro Shimizu 890ddd
				TImageReaderP ir = lr->getFrameReader(it->first);
Toshihiro Shimizu 890ddd
				TRasterImageP img = ir->load();
Toshihiro Shimizu 890ddd
				double dpix, dpiy;
Toshihiro Shimizu 890ddd
				img->getDpi(dpix, dpiy);
Toshihiro Shimizu 890ddd
				TRasterCM32P raster(convert(img->getBBox()).getSize());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TRop::convert(raster, img->getRaster());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				TImageWriterP iw = lw->getFrameWriter(it->first);
Toshihiro Shimizu 890ddd
				TToonzImageP outimg(raster, raster->getBounds());
Toshihiro Shimizu 890ddd
				outimg->setDpi(dpix, dpiy);
Toshihiro Shimizu 890ddd
				outimg->setPalette(plt);
Toshihiro Shimizu 890ddd
				iw->save(outimg);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			} catch (...) {
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
				//string msg="Frame "+toString(it->first.getNumber())+": conversion failed!";
Toshihiro Shimizu 890ddd
				//cout << msg << endl;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFilePath pltPath = lw->getFilePath().withNoFrame().withType("tpl");
Toshihiro Shimizu 890ddd
		if (TSystem::touchParentDir(pltPath)) {
Toshihiro Shimizu 890ddd
			if (TSystem::doesExistFileOrLevel(pltPath))
Toshihiro Shimizu 890ddd
				TSystem::removeFileOrLevel(pltPath);
Toshihiro Shimizu 890ddd
			TOStream os(pltPath);
Toshihiro Shimizu 890ddd
			os << plt;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		lr = TLevelReaderP();
Toshihiro Shimizu 890ddd
		lw = TLevelWriterP();
Toshihiro Shimizu 890ddd
		//delete plt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ToonzImageUtils::eraseImage(const TToonzImageP &ti, const TRaster32P &image, const TPoint &pos,
Toshihiro Shimizu 890ddd
								 bool invert, bool eraseInk, bool erasePaint, bool selective, int styleId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRect rasBounds = ti->getRaster()->getBounds();
Toshihiro Shimizu 890ddd
	TRect imageBounds = image->getBounds() + pos;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (invert) {
Toshihiro Shimizu 890ddd
		/*----------------------------------------
Toshihiro Shimizu 890ddd
	  	┌───┬─┐
Toshihiro Shimizu 890ddd
	  	│③  │②│
Toshihiro Shimizu 890ddd
	  	├─┬─┤ │
Toshihiro Shimizu 890ddd
	  	│④│★│ │
Toshihiro Shimizu 890ddd
	  	│ ├─┴─┤
Toshihiro Shimizu 890ddd
	  	│ │①  │
Toshihiro Shimizu 890ddd
	  	└─┴───┘
Toshihiro Shimizu 890ddd
	   ★はFreeHandで囲んだ領域のバウンディングボックス
Toshihiro Shimizu 890ddd
	   外側のワクはラスタ画像のフチ
Toshihiro Shimizu 890ddd
	  -----------------------------------------*/
Toshihiro Shimizu 890ddd
		TRect rect;
Toshihiro Shimizu 890ddd
		/*- ①の部分を消す -*/
Toshihiro Shimizu 890ddd
		if (rasBounds.y0 != imageBounds.y0) {
Toshihiro Shimizu 890ddd
			rect = TRect(imageBounds.x0, rasBounds.y0, rasBounds.x1, imageBounds.y0);
Toshihiro Shimizu 890ddd
			ToonzImageUtils::eraseRect(ti, ToonzImageUtils::convertRasterToWorld(rect, ti),
Toshihiro Shimizu 890ddd
									   selective ? styleId : -1, eraseInk, erasePaint);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		/*- ②の部分を消す -*/
Toshihiro Shimizu 890ddd
		if (imageBounds.x1 != rasBounds.x1) {
Toshihiro Shimizu 890ddd
			rect = TRect(imageBounds.x1, imageBounds.y0, rasBounds.x1, rasBounds.y1);
Toshihiro Shimizu 890ddd
			ToonzImageUtils::eraseRect(ti, ToonzImageUtils::convertRasterToWorld(rect, ti),
Toshihiro Shimizu 890ddd
									   selective ? styleId : -1, eraseInk, erasePaint);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		/*- ③の部分を消す -*/
Toshihiro Shimizu 890ddd
		if (imageBounds.y1 != rasBounds.y1) {
Toshihiro Shimizu 890ddd
			rect = TRect(rasBounds.x0, imageBounds.y1, imageBounds.x1, rasBounds.y1);
Toshihiro Shimizu 890ddd
			ToonzImageUtils::eraseRect(ti, ToonzImageUtils::convertRasterToWorld(rect, ti),
Toshihiro Shimizu 890ddd
									   selective ? styleId : -1, eraseInk, erasePaint);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		/*- ④の部分を消す -*/
Toshihiro Shimizu 890ddd
		if (rasBounds.x0 != imageBounds.x0) {
Toshihiro Shimizu 890ddd
			rect = TRect(rasBounds.x0, rasBounds.y0, imageBounds.x0, imageBounds.y1);
Toshihiro Shimizu 890ddd
			ToonzImageUtils::eraseRect(ti, ToonzImageUtils::convertRasterToWorld(rect, ti),
Toshihiro Shimizu 890ddd
									   selective ? styleId : -1, eraseInk, erasePaint);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterCM32P workRas = ti->getRaster()->extract(imageBounds);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int y;
Toshihiro Shimizu 890ddd
	for (y = 0; y < workRas->getLy(); y++) {
Toshihiro Shimizu 890ddd
		TPixelCM32 *outPix = workRas->pixels(y);
Toshihiro Shimizu 890ddd
		TPixelCM32 *outEndPix = outPix + workRas->getLx();
Toshihiro Shimizu 890ddd
		TPixel32 *inPix = image->pixels(y);
Toshihiro Shimizu 890ddd
		for (outPix; outPix != outEndPix; outPix++, inPix++) {
Toshihiro Shimizu 890ddd
			bool canEraseInk = !selective || (selective && styleId == outPix->getInk());
Toshihiro Shimizu 890ddd
			bool canErasePaint = !selective || (selective && styleId == outPix->getPaint());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int paint, tone;
Toshihiro Shimizu 890ddd
			if (!invert) {
Toshihiro Shimizu 890ddd
				paint = inPix->m > 0 && erasePaint && canErasePaint ? 0 : outPix->getPaint();
Toshihiro Shimizu 890ddd
				tone = inPix->m > 0 && eraseInk && canEraseInk ? tmax(outPix->getTone(), (int)inPix->m) : outPix->getTone();
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				paint = inPix->m < 255 && erasePaint && canErasePaint ? 0 : outPix->getPaint();
Toshihiro Shimizu 890ddd
				tone = inPix->m < 255 && eraseInk && canEraseInk ? tmax(outPix->getTone(), 255 - (int)inPix->m) : outPix->getTone();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			*outPix = TPixelCM32(outPix->getInk(), paint, tone);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 3bfa54
std::string ToonzImageUtils::premultiply(const TFilePath &levelPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(0);
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
if (levelPath==TFilePath())
Toshihiro Shimizu 890ddd
  return "";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
if(!TSystem::doesExistFileOrLevel(levelPath))
Toshihiro Shimizu 890ddd
  return string("Can't find level")+toString(levelPath.getWideString());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFileType::Type type = TFileType::getInfo(levelPath);
Toshihiro Shimizu 890ddd
if(type == TFileType::CMAPPED_LEVEL)
Toshihiro Shimizu 890ddd
  return "Cannot premultiply the selected file.";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
if (type == TFileType::VECTOR_LEVEL || type == TFileType::VECTOR_IMAGE)
Toshihiro Shimizu 890ddd
  return "Cannot premultiply a vector-based level.";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
if (type != TFileType::RASTER_LEVEL && type != TFileType::RASTER_IMAGE)
Toshihiro Shimizu 890ddd
  return "Cannot premultiply the selected file.";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
try 
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
  TLevelReaderP lr = TLevelReaderP(levelPath);
Toshihiro Shimizu 890ddd
  if (!lr) return "";    
Toshihiro Shimizu 890ddd
  TLevelP level =  lr->loadInfo();
Toshihiro Shimizu 890ddd
  if(!level || level->getFrameCount()==0) return "";
Toshihiro Shimizu 890ddd
  string format = levelPath.getType();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  TPropertyGroup* prop = 
Toshihiro Shimizu 890ddd
    TApplication::instance()
Toshihiro Shimizu 890ddd
    ->getCurrentScene()
Toshihiro Shimizu 890ddd
    ->getProperties()
Toshihiro Shimizu 890ddd
    ->getOutputProperties()
Toshihiro Shimizu 890ddd
    ->getFileFormatProperties(format)
Toshihiro Shimizu 890ddd
    ->clone();
Toshihiro Shimizu 890ddd
  assert(prop);
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  TEnumProperty *p = (TEnumProperty*)prop->getProperty("Bits Per Pixel");
Toshihiro Shimizu 890ddd
  int bpp = p?atoi((toString(p->getValue()).c_str())):32; 
Toshihiro Shimizu 890ddd
  if (bpp!=32 && bpp!=64) //non ha senso premoltiplicare senza il canale alpha...
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
    if (bpp<32)
Toshihiro Shimizu 890ddd
      p->setValue(L"32(RGBM)");
Toshihiro Shimizu 890ddd
    else 
Toshihiro Shimizu 890ddd
      p->setValue(L"64(RGBM)");
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
  bool isMovie = (format=="mov" || format=="avi" || format=="3gp");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  TLevelWriterP lw;
Toshihiro Shimizu 890ddd
  if (!isMovie)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
    lw = TLevelWriterP(levelPath, prop);
Toshihiro Shimizu 890ddd
    if (!lw) return "";
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  int count = 0;
Toshihiro Shimizu 890ddd
  TLevel::Iterator it = level->begin();
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  for (;it!=level->end(); ++it)
Toshihiro Shimizu 890ddd
    {  
Toshihiro Shimizu 890ddd
    TImageReaderP ir = lr->getFrameReader(it->first);
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    TRasterImageP rimg = (TRasterImageP)ir->load();
Toshihiro Shimizu 890ddd
    if (!rimg)
Toshihiro Shimizu 890ddd
      continue;
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    TRop::premultiply(rimg->getRaster());
Toshihiro Shimizu 890ddd
    ir = 0;
Toshihiro Shimizu 890ddd
    
Toshihiro Shimizu 890ddd
    if (isMovie)
Toshihiro Shimizu 890ddd
      level->setFrame(it->first, rimg);
Toshihiro Shimizu 890ddd
    else
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
      TImageWriterP iw = lw->getFrameWriter(it->first);	 
Toshihiro Shimizu 890ddd
      iw->save(rimg);
Toshihiro Shimizu 890ddd
      iw = 0;
Toshihiro Shimizu 890ddd
      }
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  lr = TLevelReaderP();
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  if (isMovie)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
    TSystem::deleteFile(levelPath);
Toshihiro Shimizu 890ddd
    lw = TLevelWriterP(levelPath, prop);
Toshihiro Shimizu 890ddd
    if (!lw) return "";
Toshihiro Shimizu 890ddd
    lw->save(level);
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
  if (prop)
Toshihiro Shimizu 890ddd
    delete prop;
Toshihiro Shimizu 890ddd
  }catch(...) 
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
	return "Cannot premultiply the selected file.";
Toshihiro Shimizu 890ddd
    }  
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return "";
Toshihiro Shimizu 890ddd
}