Blob Blame Raw


#include "toonz/scriptbinding_image.h"
#include "toonz/scriptbinding_level.h"
#include "toonz/scriptbinding_files.h"
#include "tsystem.h"
#include "ttoonzimage.h"
#include "tfiletype.h"
#include "timage_io.h"
#include "tlevel_io.h"

namespace TScriptBinding
{

Image::Image()
{
}

Image::Image(const TImageP img)
	: m_img(img)
{
}

Image::Image(TImage *img)
	: m_img(img)
{
}

Image::~Image()
{
}

QScriptValue Image::ctor(QScriptContext *context, QScriptEngine *engine)
{
	Image *img = new Image();
	QScriptValue obj = create(engine, img);
	QScriptValue err = checkArgumentCount(context, "the Image constructor", 0, 1);
	if (err.isError())
		return err;
	if (context->argumentCount() == 1) {
		return obj.property("load").call(obj, context->argumentsObject());
	}
	return obj;
}

QScriptValue Image::toString()
{
	if (m_img) {
		TImage::Type type = m_img->getType();
		if (type == TImage::RASTER)
			return QString("Raster image ( %1 x %2 )").arg(getWidth()).arg(getHeight());
		else if (type == TImage::TOONZ_RASTER)
			return QString("Toonz raster image ( %1 x %2 )").arg(getWidth()).arg(getHeight());
		else if (type == TImage::VECTOR)
			return QString("Vector image");
		else
			return QString("Image");
	} else {
		return "Empty image";
	}
}

int Image::getWidth()
{
	return !!m_img && !!m_img->raster() ? m_img->raster()->getSize().lx : 0;
}

int Image::getHeight()
{
	return !!m_img && !!m_img->raster() ? m_img->raster()->getSize().ly : 0;
}

double Image::getDpi()
{
	if (TRasterImageP ri = m_img) {
		double dpix = 0, dpiy = 0;
		ri->getDpi(dpix, dpiy);
		return dpix;
	} else if (TToonzImageP ti = m_img) {
		double dpix = 0, dpiy = 0;
		ti->getDpi(dpix, dpiy);
		return dpix;
	} else
		return 0;
}

QString Image::getType() const
{
	if (m_img) {
		TImage::Type type = m_img->getType();
		if (type == TImage::RASTER)
			return "Raster";
		else if (type == TImage::TOONZ_RASTER)
			return "ToonzRaster";
		else if (type == TImage::VECTOR)
			return "Vector";
		else
			return "Unknown";
	} else
		return "Empty";
}

QScriptValue Image::load(const QScriptValue &fpArg)
{
	// clear the old image (if any)
	m_img = TImageP();

	// get the path
	TFilePath fp;
	QScriptValue err = checkFilePath(context(), fpArg, fp);
	if (err.isError())
		return err;
	QString fpStr = fpArg.toString();

	try {

		// check if the file/level does exist
		if (!TSystem::doesExistFileOrLevel(fp)) {
			return context()->throwError(tr("File %1 doesn't exist").arg(fpStr));
		}

		// the file could be a level
		TFileType::Type fileType = TFileType::getInfo(fp);
		if (TFileType::isLevel(fileType)) {
			// file is a level: read first frame
			TLevelReaderP lr(fp);
			TLevelP level = lr->loadInfo();
			int n = level->getFrameCount();
			if (n > 0) {
				// there are some frames
				TFrameId fid = fp.getFrame();
				if (fid == TFrameId::NO_FRAME || fid == TFrameId::EMPTY_FRAME)
					fid = level->begin()->first;

				m_img = lr->getFrameReader(fid)->load();
				if (!m_img) {
					return context()->throwError(QString("Could not read %1").arg(fpStr));
				}
				m_img->setPalette(level->getPalette());
				if (n > 1 && (fp.getFrame() == TFrameId::EMPTY_FRAME || fp.getFrame() == TFrameId::NO_FRAME)) {
					// warning: a multi-frame level read into an Image
					warning(tr("Loaded first frame of %1").arg(n));
				}
			} else {
				// level contains no frame (not sure it can even happen)
				return context()->throwError(QString("%1 contains no frames").arg(fpStr));
			}
		} else {
			// plain image: try to read it
			if (!TImageReader::load(fp, m_img)) {
				return context()->throwError(QString("File %1 not found or not readable").arg(fpStr));
			}
		}
		// return a reference to the Image object
		return context()->thisObject();
	} catch (...) {
		return context()->throwError(tr("Unexpected error while reading image").arg(fpStr));
	}
}

QScriptValue Image::save(const QScriptValue &fpArg)
{
	// clear the old image (if any)
	if (!m_img) {
		return context()->throwError("Can't save an empty image");
	}

	// get the path
	TFilePath fp;
	QScriptValue err = checkFilePath(context(), fpArg, fp);
	if (err.isError())
		return err;
	QString fpStr = fpArg.toString();

	// handle conversion (if it is needed and possible)
	TFileType::Type fileType = TFileType::getInfo(fp);

	bool isCompatible = false;
	if (TFileType::isFullColor(fileType)) {
		if (m_img->getType() == TImage::RASTER)
			isCompatible = true;
	} else if (TFileType::isVector(fileType)) {
		if (m_img->getType() == TImage::VECTOR)
			isCompatible = true;
	} else if (fileType & TFileType::CMAPPED_IMAGE) {
		if (m_img->getType() == TImage::TOONZ_RASTER)
			isCompatible = true;
	} else {
		return context()->throwError(tr("Unrecognized file type :").arg(fpStr));
	}
	if (!isCompatible) {
		return context()->throwError(tr("Can't save a %1 image to this file type : %2").arg(getType()).arg(fpStr));
	}

	try {
		if (TFileType::isLevel(fileType)) {
			TLevelP level = new TLevel();
			level->setPalette(m_img->getPalette());
			level->setFrame(TFrameId(1), m_img);
			TLevelWriterP lw(fp);
			if (m_img->getPalette())
				lw->setPalette(m_img->getPalette());
			lw->save(level);
		} else {
			TImageWriterP iw(fp);
			iw->save(fp, m_img);
		}
		// return a reference to the Image object
		return context()->thisObject();
	} catch (...) {
		return context()->throwError(tr("Unexpected error while writing image").arg(fpStr));
	}
}

QScriptValue checkImage(QScriptContext *context, const QScriptValue &value, Image *&img)
{
	img = qscriptvalue_cast<Image *>(value);
	if (!img || !img->getImg())
		return context->throwError(QObject::tr("Bad argument (%1): should be an Image (not empty)").arg(value.toString()));
	else
		return QScriptValue();
}

} // namespace TScriptBinding