#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