Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/scriptbinding_image.h"
Toshihiro Shimizu 890ddd
#include "toonz/scriptbinding_level.h"
Toshihiro Shimizu 890ddd
#include "toonz/scriptbinding_files.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "tfiletype.h"
Toshihiro Shimizu 890ddd
#include "timage_io.h"
Toshihiro Shimizu 890ddd
#include "tlevel_io.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace TScriptBinding
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Image::Image()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Image::Image(const TImageP img)
Toshihiro Shimizu 890ddd
	: m_img(img)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Image::Image(TImage *img)
Toshihiro Shimizu 890ddd
	: m_img(img)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Image::~Image()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QScriptValue Image::ctor(QScriptContext *context, QScriptEngine *engine)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Image *img = new Image();
Toshihiro Shimizu 890ddd
	QScriptValue obj = create(engine, img);
Toshihiro Shimizu 890ddd
	QScriptValue err = checkArgumentCount(context, "the Image constructor", 0, 1);
Toshihiro Shimizu 890ddd
	if (err.isError())
Toshihiro Shimizu 890ddd
		return err;
Toshihiro Shimizu 890ddd
	if (context->argumentCount() == 1) {
Toshihiro Shimizu 890ddd
		return obj.property("load").call(obj, context->argumentsObject());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return obj;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QScriptValue Image::toString()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_img) {
Toshihiro Shimizu 890ddd
		TImage::Type type = m_img->getType();
Toshihiro Shimizu 890ddd
		if (type == TImage::RASTER)
Toshihiro Shimizu 890ddd
			return QString("Raster image ( %1 x %2 )").arg(getWidth()).arg(getHeight());
Toshihiro Shimizu 890ddd
		else if (type == TImage::TOONZ_RASTER)
Toshihiro Shimizu 890ddd
			return QString("Toonz raster image ( %1 x %2 )").arg(getWidth()).arg(getHeight());
Toshihiro Shimizu 890ddd
		else if (type == TImage::VECTOR)
Toshihiro Shimizu 890ddd
			return QString("Vector image");
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return QString("Image");
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		return "Empty image";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int Image::getWidth()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return !!m_img && !!m_img->raster() ? m_img->raster()->getSize().lx : 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int Image::getHeight()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return !!m_img && !!m_img->raster() ? m_img->raster()->getSize().ly : 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double Image::getDpi()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (TRasterImageP ri = m_img) {
Toshihiro Shimizu 890ddd
		double dpix = 0, dpiy = 0;
Toshihiro Shimizu 890ddd
		ri->getDpi(dpix, dpiy);
Toshihiro Shimizu 890ddd
		return dpix;
Toshihiro Shimizu 890ddd
	} else if (TToonzImageP ti = m_img) {
Toshihiro Shimizu 890ddd
		double dpix = 0, dpiy = 0;
Toshihiro Shimizu 890ddd
		ti->getDpi(dpix, dpiy);
Toshihiro Shimizu 890ddd
		return dpix;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString Image::getType() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_img) {
Toshihiro Shimizu 890ddd
		TImage::Type type = m_img->getType();
Toshihiro Shimizu 890ddd
		if (type == TImage::RASTER)
Toshihiro Shimizu 890ddd
			return "Raster";
Toshihiro Shimizu 890ddd
		else if (type == TImage::TOONZ_RASTER)
Toshihiro Shimizu 890ddd
			return "ToonzRaster";
Toshihiro Shimizu 890ddd
		else if (type == TImage::VECTOR)
Toshihiro Shimizu 890ddd
			return "Vector";
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return "Unknown";
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		return "Empty";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QScriptValue Image::load(const QScriptValue &fpArg)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// clear the old image (if any)
Toshihiro Shimizu 890ddd
	m_img = TImageP();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// get the path
Toshihiro Shimizu 890ddd
	TFilePath fp;
Toshihiro Shimizu 890ddd
	QScriptValue err = checkFilePath(context(), fpArg, fp);
Toshihiro Shimizu 890ddd
	if (err.isError())
Toshihiro Shimizu 890ddd
		return err;
Toshihiro Shimizu 890ddd
	QString fpStr = fpArg.toString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// check if the file/level does exist
Toshihiro Shimizu 890ddd
		if (!TSystem::doesExistFileOrLevel(fp)) {
Toshihiro Shimizu 890ddd
			return context()->throwError(tr("File %1 doesn't exist").arg(fpStr));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// the file could be a level
Toshihiro Shimizu 890ddd
		TFileType::Type fileType = TFileType::getInfo(fp);
Toshihiro Shimizu 890ddd
		if (TFileType::isLevel(fileType)) {
Toshihiro Shimizu 890ddd
			// file is a level: read first frame
Toshihiro Shimizu 890ddd
			TLevelReaderP lr(fp);
Toshihiro Shimizu 890ddd
			TLevelP level = lr->loadInfo();
Toshihiro Shimizu 890ddd
			int n = level->getFrameCount();
Toshihiro Shimizu 890ddd
			if (n > 0) {
Toshihiro Shimizu 890ddd
				// there are some frames
Toshihiro Shimizu 890ddd
				TFrameId fid = fp.getFrame();
Toshihiro Shimizu 890ddd
				if (fid == TFrameId::NO_FRAME || fid == TFrameId::EMPTY_FRAME)
Toshihiro Shimizu 890ddd
					fid = level->begin()->first;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				m_img = lr->getFrameReader(fid)->load();
Toshihiro Shimizu 890ddd
				if (!m_img) {
Toshihiro Shimizu 890ddd
					return context()->throwError(QString("Could not read %1").arg(fpStr));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				m_img->setPalette(level->getPalette());
Toshihiro Shimizu 890ddd
				if (n > 1 && (fp.getFrame() == TFrameId::EMPTY_FRAME || fp.getFrame() == TFrameId::NO_FRAME)) {
Toshihiro Shimizu 890ddd
					// warning: a multi-frame level read into an Image
Toshihiro Shimizu 890ddd
					warning(tr("Loaded first frame of %1").arg(n));
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				// level contains no frame (not sure it can even happen)
Toshihiro Shimizu 890ddd
				return context()->throwError(QString("%1 contains no frames").arg(fpStr));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			// plain image: try to read it
Toshihiro Shimizu 890ddd
			if (!TImageReader::load(fp, m_img)) {
Toshihiro Shimizu 890ddd
				return context()->throwError(QString("File %1 not found or not readable").arg(fpStr));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		// return a reference to the Image object
Toshihiro Shimizu 890ddd
		return context()->thisObject();
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
		return context()->throwError(tr("Unexpected error while reading image").arg(fpStr));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QScriptValue Image::save(const QScriptValue &fpArg)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// clear the old image (if any)
Toshihiro Shimizu 890ddd
	if (!m_img) {
Toshihiro Shimizu 890ddd
		return context()->throwError("Can't save an empty image");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// get the path
Toshihiro Shimizu 890ddd
	TFilePath fp;
Toshihiro Shimizu 890ddd
	QScriptValue err = checkFilePath(context(), fpArg, fp);
Toshihiro Shimizu 890ddd
	if (err.isError())
Toshihiro Shimizu 890ddd
		return err;
Toshihiro Shimizu 890ddd
	QString fpStr = fpArg.toString();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// handle conversion (if it is needed and possible)
Toshihiro Shimizu 890ddd
	TFileType::Type fileType = TFileType::getInfo(fp);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool isCompatible = false;
Toshihiro Shimizu 890ddd
	if (TFileType::isFullColor(fileType)) {
Toshihiro Shimizu 890ddd
		if (m_img->getType() == TImage::RASTER)
Toshihiro Shimizu 890ddd
			isCompatible = true;
Toshihiro Shimizu 890ddd
	} else if (TFileType::isVector(fileType)) {
Toshihiro Shimizu 890ddd
		if (m_img->getType() == TImage::VECTOR)
Toshihiro Shimizu 890ddd
			isCompatible = true;
Toshihiro Shimizu 890ddd
	} else if (fileType & TFileType::CMAPPED_IMAGE) {
Toshihiro Shimizu 890ddd
		if (m_img->getType() == TImage::TOONZ_RASTER)
Toshihiro Shimizu 890ddd
			isCompatible = true;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		return context()->throwError(tr("Unrecognized file type :").arg(fpStr));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (!isCompatible) {
Toshihiro Shimizu 890ddd
		return context()->throwError(tr("Can't save a %1 image to this file type : %2").arg(getType()).arg(fpStr));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		if (TFileType::isLevel(fileType)) {
Toshihiro Shimizu 890ddd
			TLevelP level = new TLevel();
Toshihiro Shimizu 890ddd
			level->setPalette(m_img->getPalette());
Toshihiro Shimizu 890ddd
			level->setFrame(TFrameId(1), m_img);
Toshihiro Shimizu 890ddd
			TLevelWriterP lw(fp);
Toshihiro Shimizu 890ddd
			if (m_img->getPalette())
Toshihiro Shimizu 890ddd
				lw->setPalette(m_img->getPalette());
Toshihiro Shimizu 890ddd
			lw->save(level);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TImageWriterP iw(fp);
Toshihiro Shimizu 890ddd
			iw->save(fp, m_img);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		// return a reference to the Image object
Toshihiro Shimizu 890ddd
		return context()->thisObject();
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
		return context()->throwError(tr("Unexpected error while writing image").arg(fpStr));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QScriptValue checkImage(QScriptContext *context, const QScriptValue &value, Image *&img)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	img = qscriptvalue_cast(value);
Toshihiro Shimizu 890ddd
	if (!img || !img->getImg())
Toshihiro Shimizu 890ddd
		return context->throwError(QObject::tr("Bad argument (%1): should be an Image (not empty)").arg(value.toString()));
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return QScriptValue();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace TScriptBinding