justburner 64e039
justburner 64e039
#include "tiio_apng.h"
justburner 64e039
#include "tsystem.h"
justburner 64e039
#include "trasterimage.h"
justburner 64e039
#include "tsound.h"
justburner 64e039
#include "timageinfo.h"
justburner 64e039
#include "toonz/stage.h"
justburner 64e039
#include <qstringlist></qstringlist>
justburner 64e039
justburner 64e039
//===========================================================
justburner 64e039
//
justburner 64e039
//  TImageWriterAPng
justburner 64e039
//
justburner 64e039
//===========================================================
justburner 64e039
justburner 64e039
class TImageWriterAPng : public TImageWriter {
justburner 64e039
public:
justburner 64e039
  int m_frameIndex;
justburner 64e039
justburner 64e039
  TImageWriterAPng(const TFilePath &path, int frameIndex, TLevelWriterAPng *lwg)
justburner 64e039
      : TImageWriter(path), m_frameIndex(frameIndex), m_lwg(lwg) {
justburner 64e039
    m_lwg->addRef();
justburner 64e039
  }
justburner 64e039
  ~TImageWriterAPng() { m_lwg->release(); }
justburner 64e039
justburner 64e039
  bool is64bitOutputSupported() override { return false; }
justburner 64e039
  void save(const TImageP &img) override { m_lwg->save(img, m_frameIndex); }
justburner 64e039
justburner 64e039
private:
justburner 64e039
  TLevelWriterAPng *m_lwg;
justburner 64e039
};
justburner 64e039
justburner 64e039
//===========================================================
justburner 64e039
//
justburner 64e039
//  TLevelWriterAPng;
justburner 64e039
//
justburner 64e039
//===========================================================
justburner 64e039
justburner 64e039
TLevelWriterAPng::TLevelWriterAPng(const TFilePath &path, TPropertyGroup *winfo)
justburner 64e039
    : TLevelWriter(path, winfo) {
justburner 64e039
  if (!m_properties) m_properties = new Tiio::APngWriterProperties();
justburner 64e039
justburner 64e039
  std::string scale = m_properties->getProperty("Scale")->getValueAsString();
justburner 64e039
  m_scale           = QString::fromStdString(scale).toInt();
justburner 64e039
justburner 64e039
  TBoolProperty *extPng = (TBoolProperty *)m_properties->getProperty("ExtPng");
justburner 64e039
  m_extPng              = extPng->getValue();
justburner 64e039
justburner 64e039
  TBoolProperty *loop = (TBoolProperty *)m_properties->getProperty("Looping");
justburner 64e039
  m_looping           = loop->getValue();
justburner 64e039
justburner 64e039
  if (m_extPng) {
justburner 64e039
    m_path = m_path.getParentDir() + TFilePath(m_path.getWideName() + L".png");
justburner 64e039
  }
justburner 64e039
justburner 64e039
  ffmpegWriter = new Ffmpeg();
justburner 64e039
  ffmpegWriter->setPath(m_path);
justburner 64e039
  if (TSystem::doesExistFileOrLevel(m_path)) TSystem::deleteFile(m_path);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------
justburner 64e039
justburner 64e039
TLevelWriterAPng::~TLevelWriterAPng() {
justburner 64e039
  QStringList preIArgs;
justburner 64e039
  QStringList postIArgs;
justburner 64e039
justburner 64e039
  int outLx = m_lx;
justburner 64e039
  int outLy = m_ly;
justburner 64e039
justburner 64e039
  // set scaling
justburner 64e039
  if (m_scale != 0) {
justburner 64e039
    outLx = m_lx * m_scale / 100;
justburner 64e039
    outLy = m_ly * m_scale / 100;
justburner 64e039
  }
justburner 64e039
  // ffmpeg doesn't like resolutions that aren't divisible by 2.
justburner 64e039
  if (outLx % 2 != 0) outLx++;
justburner 64e039
  if (outLy % 2 != 0) outLy++;
justburner 64e039
justburner 64e039
  preIArgs << "-framerate";
justburner 64e039
  preIArgs << QString::number(m_frameRate);
justburner 64e039
  postIArgs << "-plays";
justburner 64e039
  postIArgs << (m_looping ? "0" : "1");
justburner 64e039
  postIArgs << "-f";
justburner 64e039
  postIArgs << "apng";
justburner 64e039
  postIArgs << "-s";
justburner 64e039
  postIArgs << QString::number(outLx) + "x" + QString::number(outLy);
justburner 64e039
justburner 64e039
  ffmpegWriter->runFfmpeg(preIArgs, postIArgs, false, false, true);
justburner 64e039
  ffmpegWriter->cleanUpFiles();
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------
justburner 64e039
justburner 64e039
TImageWriterP TLevelWriterAPng::getFrameWriter(TFrameId fid) {
justburner 64e039
  if (!fid.getLetter().isEmpty()) return TImageWriterP(0);
justburner 64e039
  int index             = fid.getNumber();
justburner 64e039
  TImageWriterAPng *iwg = new TImageWriterAPng(m_path, index, this);
justburner 64e039
  return TImageWriterP(iwg);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------
justburner 64e039
void TLevelWriterAPng::setFrameRate(double fps) {
justburner 64e039
  m_frameRate = fps;
justburner 64e039
  ffmpegWriter->setFrameRate(fps);
justburner 64e039
}
justburner 64e039
justburner 64e039
void TLevelWriterAPng::saveSoundTrack(TSoundTrack *st) {
justburner 64e039
  ffmpegWriter->saveSoundTrack(st);
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------
justburner 64e039
justburner 64e039
void TLevelWriterAPng::save(const TImageP &img, int frameIndex) {
justburner 64e039
  TRasterImageP image(img);
justburner 64e039
  m_lx = image->getRaster()->getLx();
justburner 64e039
  m_ly = image->getRaster()->getLy();
justburner 64e039
  ffmpegWriter->createIntermediateImage(img, frameIndex);
justburner 64e039
}
justburner 64e039
justburner 64e039
//===========================================================
justburner 64e039
//
justburner 64e039
//  TImageReaderAPng
justburner 64e039
//
justburner 64e039
//===========================================================
justburner 64e039
justburner 64e039
class TImageReaderAPng final : public TImageReader {
justburner 64e039
public:
justburner 64e039
  int m_frameIndex;
justburner 64e039
justburner 64e039
  TImageReaderAPng(const TFilePath &path, int index, TLevelReaderAPng *lra,
justburner 64e039
                   TImageInfo *info)
justburner 64e039
      : TImageReader(path), m_lra(lra), m_frameIndex(index), m_info(info) {
justburner 64e039
    m_lra->addRef();
justburner 64e039
  }
justburner 64e039
  ~TImageReaderAPng() { m_lra->release(); }
justburner 64e039
justburner 64e039
  TImageP load() override { return m_lra->load(m_frameIndex); }
justburner 64e039
  TDimension getSize() const { return m_lra->getSize(); }
justburner 64e039
  TRect getBBox() const { return TRect(); }
justburner 64e039
  const TImageInfo *getImageInfo() const override { return m_info; }
justburner 64e039
justburner 64e039
private:
justburner 64e039
  TLevelReaderAPng *m_lra;
justburner 64e039
  TImageInfo *m_info;
justburner 64e039
justburner 64e039
  // not implemented
justburner 64e039
  TImageReaderAPng(const TImageReaderAPng &);
justburner 64e039
  TImageReaderAPng &operator=(const TImageReaderAPng &src);
justburner 64e039
};
justburner 64e039
justburner 64e039
//===========================================================
justburner 64e039
//
justburner 64e039
//  TLevelReaderAPng
justburner 64e039
//
justburner 64e039
//===========================================================
justburner 64e039
justburner 64e039
TLevelReaderAPng::TLevelReaderAPng(const TFilePath &path) : TLevelReader(path) {
justburner 64e039
  ffmpegReader = new Ffmpeg();
justburner 64e039
  ffmpegReader->setPath(m_path);
justburner 64e039
  ffmpegReader->disablePrecompute();
justburner 64e039
  ffmpegFileInfo tempInfo = ffmpegReader->getInfo();
justburner 64e039
  double fps              = tempInfo.m_frameRate;
justburner 64e039
  m_frameCount            = tempInfo.m_frameCount;
justburner 64e039
  m_size                  = TDimension(tempInfo.m_lx, tempInfo.m_ly);
justburner 64e039
  m_lx                    = m_size.lx;
justburner 64e039
  m_ly                    = m_size.ly;
justburner 64e039
justburner 64e039
  // set values
justburner 64e039
  m_info                   = new TImageInfo();
justburner 64e039
  m_info->m_frameRate      = fps;
justburner 64e039
  m_info->m_lx             = m_lx;
justburner 64e039
  m_info->m_ly             = m_ly;
justburner 64e039
  m_info->m_bitsPerSample  = 8;
justburner 64e039
  m_info->m_samplePerPixel = 4;
justburner 64e039
  m_info->m_dpix           = Stage::standardDpi;
justburner 64e039
  m_info->m_dpiy           = Stage::standardDpi;
justburner 64e039
}
justburner 64e039
//-----------------------------------------------------------
justburner 64e039
justburner 64e039
TLevelReaderAPng::~TLevelReaderAPng() {}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------
justburner 64e039
justburner 64e039
TLevelP TLevelReaderAPng::loadInfo() {
justburner 64e039
  if (m_frameCount == -1) return TLevelP();
justburner 64e039
  TLevelP level;
justburner 64e039
  for (int i = 1; i <= m_frameCount; i++) level->setFrame(i, TImageP());
justburner 64e039
  return level;
justburner 64e039
}
justburner 64e039
justburner 64e039
//-----------------------------------------------------------
justburner 64e039
justburner 64e039
TImageReaderP TLevelReaderAPng::getFrameReader(TFrameId fid) {
justburner 64e039
  if (!fid.getLetter().isEmpty()) return TImageReaderP(0);
justburner 64e039
  int index = fid.getNumber();
justburner 64e039
justburner 64e039
  TImageReaderAPng *irm = new TImageReaderAPng(m_path, index, this, m_info);
justburner 64e039
  return TImageReaderP(irm);
justburner 64e039
}
justburner 64e039
justburner 64e039
//------------------------------------------------------------------------------
justburner 64e039
justburner 64e039
TDimension TLevelReaderAPng::getSize() { return m_size; }
justburner 64e039
justburner 64e039
//------------------------------------------------
justburner 64e039
justburner 64e039
TImageP TLevelReaderAPng::load(int frameIndex) {
justburner 64e039
  if (!ffmpegFramesCreated) {
justburner 64e039
    ffmpegReader->getFramesFromMovie();
justburner 64e039
    ffmpegFramesCreated = true;
justburner 64e039
  }
justburner 64e039
  return ffmpegReader->getImage(frameIndex);
justburner 64e039
}
justburner 64e039
justburner 64e039
Tiio::APngWriterProperties::APngWriterProperties()
justburner 64e039
    : m_scale("Scale", 1, 100, 100)
justburner 64e039
    , m_looping("Looping", true)
justburner 64e039
    , m_extPng("ExtPng", false) {
justburner 64e039
  bind(m_scale);
justburner 64e039
  bind(m_looping);
justburner 64e039
  bind(m_extPng);
justburner 64e039
}
justburner 64e039
justburner 64e039
void Tiio::APngWriterProperties::updateTranslation() {
justburner 64e039
  m_scale.setQStringName(tr("Scale"));
justburner 64e039
  m_looping.setQStringName(tr("Looping"));
justburner 64e039
  m_extPng.setQStringName(tr("Write as .png"));
justburner 64e039
}