Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/scriptbinding_image_builder.h"
Toshihiro Shimizu 890ddd
#include "toonz/scriptbinding_image.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Shinya Kitaoka d4642c
#include <cmath></cmath>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace TScriptBinding {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Transform::Transform() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Transform::Transform(const TAffine &aff) : m_affine(aff) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Transform::~Transform() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue Transform::ctor(QScriptContext *context, QScriptEngine *engine) {
Shinya Kitaoka 120a6e
  return create(engine, new Transform());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue Transform::toString() {
Shinya Kitaoka 120a6e
  if (m_affine.isIdentity())
Shinya Kitaoka 120a6e
    return tr("Identity");
Shinya Kitaoka 120a6e
  else if (m_affine.isTranslation())
Shinya Kitaoka 120a6e
    return tr("Translation(%1,%2)").arg(m_affine.a13).arg(m_affine.a23);
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    QString translationPart = "";
Shinya Kitaoka 120a6e
    if (m_affine.a13 != 0.0 || m_affine.a23 != 0.0)
Shinya Kitaoka 120a6e
      translationPart =
Shinya Kitaoka 120a6e
          tr("Translation(%1,%2)").arg(m_affine.a13).arg(m_affine.a23);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (fabs(m_affine.det() - 1.0) < 1.0e-8) {
Shinya Kitaoka 120a6e
      double phi           = atan2(m_affine.a12, m_affine.a11) * 180.0 / M_PI;
Shinya Kitaoka 120a6e
      phi                  = -(0.001 * floor(1000 * phi + 0.5));
Shinya Kitaoka 120a6e
      QString rotationPart = tr("Rotation(%1)").arg(phi);
Shinya Kitaoka 120a6e
      if (translationPart == "")
Shinya Kitaoka 120a6e
        return rotationPart;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        return translationPart + "*" + rotationPart;
Shinya Kitaoka 120a6e
    } else if (m_affine.a12 == 0.0 && m_affine.a21 == 0.0) {
Shinya Kitaoka 120a6e
      QString scalePart;
Shinya Kitaoka 120a6e
      if (m_affine.a11 == m_affine.a22)
Shinya Kitaoka 120a6e
        scalePart = tr("Scale(%1%)").arg(m_affine.a11 * 100);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        scalePart = tr("Scale(%1%, %2%)")
Shinya Kitaoka 120a6e
                        .arg(m_affine.a11 * 100)
Shinya Kitaoka 120a6e
                        .arg(m_affine.a22 * 100);
Shinya Kitaoka 120a6e
      if (translationPart == "")
Shinya Kitaoka 120a6e
        return scalePart;
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        return translationPart + "*" + scalePart;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      return tr("Transform(%1, %2, %3;  %4, %5, %6)")
Shinya Kitaoka 120a6e
          .arg(m_affine.a11)
Shinya Kitaoka 120a6e
          .arg(m_affine.a12)
Shinya Kitaoka 120a6e
          .arg(m_affine.a13)
Shinya Kitaoka 120a6e
          .arg(m_affine.a21)
Shinya Kitaoka 120a6e
          .arg(m_affine.a22)
Shinya Kitaoka 120a6e
          .arg(m_affine.a23);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue Transform::translate(double x, double y) {
Shinya Kitaoka 120a6e
  return create(engine(), new Transform(TTranslation(x, y) * m_affine));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue Transform::rotate(double degrees) {
Shinya Kitaoka 120a6e
  return create(engine(), new Transform(TRotation(degrees) * m_affine));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue Transform::scale(double s) {
Shinya Kitaoka 120a6e
  return create(engine(), new Transform(TScale(s) * m_affine));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue Transform::scale(double sx, double sy) {
Shinya Kitaoka 120a6e
  return create(engine(), new Transform(TScale(sx, sy) * m_affine));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ImageBuilder::ImageBuilder() : m_width(0), m_height(0) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ImageBuilder::~ImageBuilder() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue ImageBuilder::ctor(QScriptContext *context,
Shinya Kitaoka 120a6e
                                QScriptEngine *engine) {
Shinya Kitaoka 120a6e
  ImageBuilder *imageBuilder = 0;
Shinya Kitaoka 120a6e
  if (context->argumentCount() == 2 || context->argumentCount() == 3) {
Shinya Kitaoka 120a6e
    if (!context->argument(0).isNumber() || !context->argument(1).isNumber())
Shinya Kitaoka 120a6e
      return context->throwError("Bad arguments: expected width,height[,type]");
Shinya Kitaoka 120a6e
    int width  = (int)(context->argument(0).toNumber());
Shinya Kitaoka 120a6e
    int height = (int)(context->argument(1).toNumber());
Shinya Kitaoka 120a6e
    if (width <= 0 || height <= 0) return context->throwError("Bad size");
Shinya Kitaoka 120a6e
    QString type;
Shinya Kitaoka 120a6e
    if (context->argumentCount() == 3) {
Shinya Kitaoka 120a6e
      if (context->argument(2).isString())
Shinya Kitaoka 120a6e
        type = context->argument(2).toString();
Shinya Kitaoka 120a6e
      if (type != "Raster" && type != "ToonzRaster")
Shinya Kitaoka 120a6e
        return context->throwError(
Shinya Kitaoka 120a6e
            tr("Bad argument (%1): should be 'Raster' or ToonzRaster'")
Shinya Kitaoka 120a6e
                .arg(context->argument(2).toString()));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    imageBuilder           = new ImageBuilder();
Shinya Kitaoka 120a6e
    imageBuilder->m_width  = width;
Shinya Kitaoka 120a6e
    imageBuilder->m_height = height;
Shinya Kitaoka 120a6e
    if (type == "Raster")
Shinya Kitaoka 120a6e
      imageBuilder->m_img = new TRasterImage(TRaster32P(width, height));
Shinya Kitaoka 120a6e
    else if (type == "ToonzRaster") {
Shinya Kitaoka 120a6e
      imageBuilder->m_img = new TToonzImage(TRasterCM32P(width, height),
Shinya Kitaoka 120a6e
                                            TRect(0, 0, width, height));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (context->argumentCount() != 0)
Shinya Kitaoka 120a6e
      return context->throwError(
Shinya Kitaoka 120a6e
          "Bad argument count. expected: width,height[,type]");
Shinya Kitaoka 120a6e
    imageBuilder = new ImageBuilder();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  QScriptValue obj =
Shinya Kitaoka 120a6e
      engine->newQObject(imageBuilder, QScriptEngine::AutoOwnership,
Shinya Kitaoka 120a6e
                         QScriptEngine::ExcludeSuperClassContents |
Shinya Kitaoka 120a6e
                             QScriptEngine::ExcludeSuperClassMethods);
Shinya Kitaoka 120a6e
  return obj;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue ImageBuilder::toString() {
Shinya Kitaoka 120a6e
  QString type = "Empty";
Shinya Kitaoka 120a6e
  if (m_img) {
Shinya Kitaoka 120a6e
    if (m_img->getType() == TImage::RASTER)
Shinya Kitaoka 120a6e
      type = "Raster";
Shinya Kitaoka 120a6e
    else if (m_img->getType() == TImage::TOONZ_RASTER)
Shinya Kitaoka 120a6e
      type = "ToonzRaster";
Shinya Kitaoka 120a6e
    else if (m_img->getType() == TImage::VECTOR)
Shinya Kitaoka 120a6e
      type = "Vector";
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      type = "Bad";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return tr("ImageBuilder(%1 image)").arg(type);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue ImageBuilder::getImage() {
Shinya Kitaoka 120a6e
  return create(engine(), new Image(m_img));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue ImageBuilder::fill(const QString &colorName) {
Shinya Kitaoka 120a6e
  QColor color;
Shinya Kitaoka 120a6e
  QScriptValue err = checkColor(context(), colorName, color);
Shinya Kitaoka 120a6e
  if (err.isError()) return err;
Shinya Kitaoka 120a6e
  TPixel32 pix(color.red(), color.green(), color.blue(), color.alpha());
Shinya Kitaoka 120a6e
  if (m_img) {
Shinya Kitaoka 120a6e
    if (m_img->getType() != TImage::RASTER)
Shinya Kitaoka 120a6e
      context()->throwError("Can't fill a non-'Raster' image");
Shinya Kitaoka 120a6e
    TRaster32P ras = m_img->raster();
Shinya Kitaoka 120a6e
    if (ras) ras->fill(pix);
Shinya Kitaoka 120a6e
  } else if (m_width > 0 && m_height > 0) {
Shinya Kitaoka 120a6e
    TRaster32P ras(m_width, m_height);
Shinya Kitaoka 120a6e
    ras->fill(pix);
Shinya Kitaoka 120a6e
    m_img = TRasterImageP(ras);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return context()->thisObject();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ImageBuilder::clear() { m_img = TImageP(); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QString ImageBuilder::add(const TImageP &img, const TAffine &aff) {
Shinya Kitaoka 120a6e
  if (fabs(aff.det()) < 0.001) return "";
Shinya Kitaoka 120a6e
  if (m_img && (m_img->getType() != img->getType()))
Shinya Kitaoka 120a6e
    return "Image type mismatch";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_img && img->getType() != TImage::VECTOR && m_width > 0 &&
Shinya Kitaoka 120a6e
      m_height > 0) {
Shinya Kitaoka 120a6e
    TRasterP ras = img->raster()->create(m_width, m_height);
Shinya Kitaoka 120a6e
    if (img->getType() == TImage::RASTER)
Shinya Kitaoka 120a6e
      m_img = TRasterImageP(ras);
Shinya Kitaoka 120a6e
    else if (img->getType() == TImage::TOONZ_RASTER) {
Shinya Kitaoka 120a6e
      m_img = TToonzImageP(ras, ras->getBounds());
Shinya Kitaoka 120a6e
      m_img->setPalette(img->getPalette());
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      return "Bad image type";
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_img && aff.isIdentity()) {
Shinya Kitaoka 120a6e
    m_img = img->cloneImage();
Shinya Kitaoka 120a6e
  } else if (img->getType() == TImage::VECTOR) {
Shinya Kitaoka 120a6e
    // vector image
Shinya Kitaoka 120a6e
    if (!m_img) {
Shinya Kitaoka 120a6e
      // transform
Shinya Kitaoka 120a6e
      TVectorImageP vi = img->cloneImage();
Shinya Kitaoka 120a6e
      vi->transform(aff);
Shinya Kitaoka 120a6e
      m_img = vi;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // merge
Shinya Kitaoka 120a6e
      TVectorImageP up = img;
Shinya Kitaoka 120a6e
      TVectorImageP dn = m_img;
Shinya Kitaoka 120a6e
      dn->mergeImage(up, aff);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (img->getType() != TImage::TOONZ_RASTER &&
Shinya Kitaoka 120a6e
        img->getType() != TImage::RASTER) {
Shinya Kitaoka 120a6e
      // this should not ever happen
Shinya Kitaoka 120a6e
      return "Bad image type";
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    TRasterP up = img->raster();
Shinya Kitaoka 120a6e
    if (!m_img) {
Shinya Kitaoka 120a6e
      // create an empty bg
Shinya Kitaoka 120a6e
      TRasterP ras = up->create();
Shinya Kitaoka 120a6e
      ras->clear();
Shinya Kitaoka 120a6e
      if (img->getType() == TImage::TOONZ_RASTER) {
Shinya Kitaoka 120a6e
        TRasterCM32P rasCm = ras;
Shinya Kitaoka 120a6e
        m_img              = TToonzImageP(rasCm,
Shinya Kitaoka 120a6e
                             TRect(0, 0, ras->getLx() - 1, ras->getLy() - 1));
Shinya Kitaoka 120a6e
        m_img->setPalette(img->getPalette());
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        m_img = TRasterImageP(ras);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    TRasterP dn = m_img->raster();
Shinya Kitaoka 120a6e
    if (aff.isTranslation() && aff.a13 == floor(aff.a13) &&
Shinya Kitaoka 120a6e
        aff.a23 == floor(aff.a23)) {
Shinya Kitaoka 120a6e
      // just a integer coord translation
Shinya Kitaoka 120a6e
      TPoint delta = -up->getCenter() + dn->getCenter() +
Shinya Kitaoka 120a6e
                     TPoint((int)aff.a13, (int)aff.a23);
Shinya Kitaoka 120a6e
      TRop::over(dn, up, delta);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      TAffine aff1 = TTranslation(dn->getCenterD()) * aff *
Shinya Kitaoka 120a6e
                     TTranslation(-up->getCenterD());
Shinya Kitaoka 120a6e
      TRop::over(dn, up, aff1, TRop::Mitchell);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return "";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  TImageP srcImg = img->getImg();
Shinya Kitaoka 120a6e
  if(srcImg->getType()==TImage::RASTER ||
Shinya Kitaoka 120a6e
  srcImg->getType()==TImage::TOONZ_RASTER)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    TRasterP in = srcImg->raster();
Toshihiro Shimizu 890ddd
    TRasterP out = in->create();
Toshihiro Shimizu 890ddd
    TPointD center = in->getCenterD();
Toshihiro Shimizu 890ddd
    TAffine aff1 = TTranslation(center) * aff * TTranslation(-center);
Toshihiro Shimizu 890ddd
    TRop::resample(out,in,aff1,TRop::Mitchell);
Toshihiro Shimizu 890ddd
    m_img = TRasterImageP(out);
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  else if(srcImg->getType()==TImage::VECTOR)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    TVectorImageP vi = srcImg->cloneImage();
Toshihiro Shimizu 890ddd
    vi->transform(aff);
Toshihiro Shimizu 890ddd
    m_img = vi;
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  else
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    return context()->throwError(tr("Bad image type"));
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  return context()->thisObject();
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue ImageBuilder::add(QScriptValue imgArg) {
Shinya Kitaoka 120a6e
  Image *simg      = 0;
Shinya Kitaoka 120a6e
  QScriptValue err = checkImage(context(), imgArg, simg);
Shinya Kitaoka 120a6e
  if (err.isError()) return err;
Shinya Kitaoka 120a6e
  QString errStr = add(simg->getImg(), TAffine());
Shinya Kitaoka 120a6e
  if (errStr != "")
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("%1 : %2").arg(errStr).arg(imgArg.toString()));
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return context()->thisObject();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QScriptValue ImageBuilder::add(QScriptValue imgArg,
Shinya Kitaoka 120a6e
                               QScriptValue transformationArg) {
Shinya Kitaoka 120a6e
  Image *simg      = 0;
Shinya Kitaoka 120a6e
  QScriptValue err = checkImage(context(), imgArg, simg);
Shinya Kitaoka 120a6e
  if (err.isError()) return err;
Shinya Kitaoka 120a6e
  Transform *transformation = qscriptvalue_cast<transform *="">(transformationArg);</transform>
Shinya Kitaoka 120a6e
  if (!transformation) {
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("Bad argument (%1): should be a Transformation")
Shinya Kitaoka 120a6e
            .arg(transformationArg.toString()));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TAffine aff    = transformation->getAffine();
Shinya Kitaoka 120a6e
  QString errStr = add(simg->getImg(), aff);
Shinya Kitaoka 120a6e
  if (errStr != "")
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("%1 : %2").arg(errStr).arg(imgArg.toString()));
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return context()->thisObject();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace TScriptBinding