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