All Classes Namespaces Functions Variables Enumerations Properties Pages
commandlineexporter.cpp
1 /*
2 
3 Pencil2D - Traditional Animation Software
4 Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5 Copyright (C) 2012-2020 Matthew Chiawen Chang
6 
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; version 2 of the License.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 */
17 
18 #include <QFileInfo>
19 #include <QTextStream>
20 
21 #include "editor.h"
22 #include "fileformat.h"
23 #include "layercamera.h"
24 #include "layermanager.h"
25 #include "mainwindow2.h"
26 #include "movieexporter.h"
27 #include "object.h"
28 #include "playbackmanager.h"
29 
30 #include "commandlineexporter.h"
31 
33  mMainWindow(mainWindow),
34  mOut(stdout, QIODevice::WriteOnly),
35  mErr(stderr, QIODevice::WriteOnly)
36 {
37 
38 }
39 
40 bool CommandLineExporter::process(const QString &inputPath,
41  const QStringList &outputPaths,
42  const QString &camera,
43  int width,
44  int height,
45  int startFrame,
46  int endFrame,
47  bool transparency)
48 {
49  LayerManager *layerManager = mMainWindow->mEditor->layers();
50 
51  if (inputPath.isEmpty())
52  {
53  // Need a file to export
54  mErr << tr("Error: No input file specified.") << endl;
55  return false;
56  }
57  QFileInfo inputFileInfo(inputPath);
58  if (!inputFileInfo.exists())
59  {
60  mErr << tr("Error: the input file at '%1' does not exist", "Command line error").arg(inputPath) << endl;
61  return false;
62  }
63  if (!inputFileInfo.isFile())
64  {
65  mErr << tr("Error: the input path '%1' is not a file", "Command line error").arg(inputPath) << endl;
66  return false;
67  }
68  Q_ASSERT(!outputPaths.empty());
69 
70  mMainWindow->openFile(inputPath);
71 
72  LayerCamera *cameraLayer = nullptr;
73  if (!camera.isEmpty())
74  {
75  cameraLayer = qobject_cast<LayerCamera*>(layerManager->findLayerByName(camera, Layer::CAMERA));
76  if (cameraLayer == nullptr)
77  {
78  mErr << tr("Warning: the specified camera layer %1 was not found, ignoring.").arg(camera) << endl;
79  }
80  }
81  if (cameraLayer == nullptr)
82  {
83  cameraLayer = qobject_cast<LayerCamera*>(layerManager->getLastCameraLayer());
84  Q_ASSERT(cameraLayer);
85  }
86 
87  if (width < 0)
88  {
89  width = cameraLayer->getViewRect().width();
90  }
91  if (height < 0)
92  {
93  height = cameraLayer->getViewRect().height();
94  }
95  QSize exportSize(width, height);
96 
97  Q_ASSERT(startFrame >= 1);
98  if (endFrame < 0)
99  {
100  endFrame = layerManager->animationLength(endFrame < -1);
101  }
102 
103  for (const QString& outputPath : outputPaths)
104  {
105  // Detect format
106  QString format = detectFormatByFileNameExtension(outputPath);
107  if (format.isNull())
108  {
109  mErr << tr("Warning: Output format is not specified or unsupported. Using PNG.", "Command line warning") << endl;
110  format = "PNG";
111  }
112 
113  if (isMovieFormat(format))
114  {
115  exportMovie(outputPath, cameraLayer, exportSize, startFrame, endFrame, transparency);
116  continue;
117  }
118 
119  exportImageSequence(outputPath, format, cameraLayer, exportSize, startFrame, endFrame, transparency);
120  }
121 
122  return true;
123 }
124 
125 void CommandLineExporter::exportMovie(const QString &outputPath,
126  const LayerCamera *cameraLayer,
127  const QSize &exportSize,
128  int startFrame,
129  int endFrame,
130  bool transparency)
131 {
132  if (transparency)
133  {
134  mErr << tr("Warning: Transparency is not currently supported in movie files", "Command line warning") << endl;
135  }
136 
137  mOut << tr("Exporting movie...", "Command line task progress") << endl;
138 
139  ExportMovieDesc desc;
140  desc.strFileName = outputPath;
141  desc.startFrame = startFrame;
142  desc.endFrame = endFrame;
143  desc.fps = mMainWindow->mEditor->playback()->fps();
144  desc.exportSize = exportSize;
145  desc.strCameraName = cameraLayer->name();
146 
147  MovieExporter ex;
148  ex.run(mMainWindow->mEditor->object(), desc, [](float, float){}, [](float){}, [](const QString &){});
149  mOut << tr("Done.", "Command line task done") << endl;
150 }
151 
152 void CommandLineExporter::exportImageSequence(const QString &outputPath,
153  const QString &format,
154  const LayerCamera *cameraLayer,
155  const QSize &exportSize,
156  int startFrame,
157  int endFrame,
158  bool transparency)
159 {
160  mOut << tr("Exporting image sequence...", "Command line task progress") << endl;
161  mMainWindow->mEditor->object()->exportFrames(startFrame,
162  endFrame,
163  cameraLayer,
164  exportSize,
165  outputPath,
166  format,
167  transparency,
168  false,
169  "",
170  true,
171  nullptr,
172  0);
173  mOut << tr("Done.", "Command line task done") << endl;
174 }
CommandLineExporter(MainWindow2 *mainWindow)
Creates a new exporter instance.
int height() const const
QTextStream & endl(QTextStream &stream)
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isNull() const const
bool isFile() const const
bool empty() const const
bool isEmpty() const const
Status run(const Object *obj, const ExportMovieDesc &desc, std::function< void(float, float)> majorProgress, std::function< void(float)> minorProgress, std::function< void(QString)> progressMessage)
Begin exporting the movie described by exportDesc.
bool exists() const const
int width() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool process(const QString &inputPath, const QStringList &outputPaths, const QString &camera, int width, int height, int startFrame, int endFrame, bool transparency)
Exports a Pencil2D file according to the specified options.
int animationLength(bool includeSounds=true)
Get the length of current project.
T qobject_cast(QObject *object)