File indexing completed on 2025-02-02 04:11:21

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "export_image_sequence_dialog.hpp"
0008 #include "ui_export_image_sequence_dialog.h"
0009 #include <QEvent>
0010 #include <QImageWriter>
0011 #include <QMessageBox>
0012 #include <QFileDialog>
0013 
0014 #include "io/raster/raster_mime.hpp"
0015 #include "math/math.hpp"
0016 
0017 class glaxnimate::gui::ExportImageSequenceDialog::Private
0018 {
0019 public:
0020     Ui::ExportImageSequenceDialog ui;
0021     model::Composition* comp;
0022 };
0023 
0024 glaxnimate::gui::ExportImageSequenceDialog::ExportImageSequenceDialog(
0025     model::Composition* comp, QDir export_path, QWidget* parent
0026 )
0027     : QDialog(parent), d(std::make_unique<Private>())
0028 {
0029     d->comp = comp;
0030     if ( !export_path.exists() )
0031         export_path = comp->document()->io_options().path;
0032 
0033     d->ui.setupUi(this);
0034     auto frame_from = comp->animation->first_frame.get();
0035     auto frame_to = comp->animation->last_frame.get();
0036     d->ui.input_frame_from->setMinimum(frame_from);
0037     d->ui.input_frame_from->setMaximum(frame_to);
0038     d->ui.input_frame_from->setValue(frame_from);
0039     d->ui.input_frame_to->setMinimum(frame_from);
0040     d->ui.input_frame_to->setMaximum(frame_to);
0041     d->ui.input_frame_to->setValue(frame_to);
0042     d->ui.input_path->setText(export_path.path());
0043 
0044     for ( const auto& ext : QImageWriter::supportedImageFormats() )
0045     {
0046         if ( ext != "svg" && ext != "svgz" )
0047             d->ui.input_format->addItem("." + QString::fromUtf8(ext), QVariant(ext));
0048     }
0049 
0050     d->ui.input_format->setCurrentText(".png");
0051 
0052     d->ui.progress_bar->hide();
0053 }
0054 
0055 glaxnimate::gui::ExportImageSequenceDialog::~ExportImageSequenceDialog() = default;
0056 
0057 void glaxnimate::gui::ExportImageSequenceDialog::changeEvent ( QEvent* e )
0058 {
0059     QDialog::changeEvent(e);
0060 
0061     if ( e->type() == QEvent::LanguageChange)
0062     {
0063         d->ui.retranslateUi(this);
0064     }
0065 }
0066 
0067 QDir glaxnimate::gui::ExportImageSequenceDialog::export_path() const
0068 {
0069     return d->ui.input_path->text();
0070 }
0071 
0072 void glaxnimate::gui::ExportImageSequenceDialog::render()
0073 {
0074     auto path = export_path();
0075     if ( !path.exists() )
0076     {
0077         // Why isn't there an easier way?
0078         auto parent = path;
0079         parent.cdUp();
0080         if ( !parent.mkpath(path.dirName()) )
0081         {
0082             QMessageBox::critical(this, i18nc("@title:window", "Error"), i18nc("%1 path", "Could not create directory\n%1", path.path()));
0083             return;
0084         }
0085     }
0086 
0087     auto name_template = d->ui.input_name->text();
0088     auto ext = d->ui.input_format->currentText();
0089     auto format = d->ui.input_format->currentData().toByteArray();
0090 
0091     auto frame_from = d->ui.input_frame_from->value();
0092     auto frame_to = d->ui.input_frame_to->value();
0093     auto frame_step = d->ui.input_frame_step->value();
0094 
0095 
0096     d->ui.progress_bar->setMinimum(frame_from);
0097     d->ui.progress_bar->setMaximum(frame_to);
0098     d->ui.progress_bar->setValue(frame_from);
0099     d->ui.progress_bar->show();
0100 
0101     auto max = std::max(std::abs(frame_from), std::abs(frame_to));
0102     auto pad = max != 0 ? std::ceil(std::log(max) / std::log(10)) : 1;
0103     for ( int f = frame_from; f < frame_to; f += frame_step )
0104     {
0105         QString frame_name = QString::number(f).rightJustified(pad, '0');
0106         QString basename = name_template;
0107         basename.append(ext);
0108         basename.replace("{frame}", frame_name);
0109 
0110         QImageWriter(path.filePath(basename), format).write(
0111             io::raster::RasterMime::frame_to_image(d->comp, f)
0112         );
0113 
0114         d->ui.progress_bar->setValue(f);
0115     }
0116 
0117     accept();
0118 }
0119 
0120 void glaxnimate::gui::ExportImageSequenceDialog::pick_path()
0121 {
0122     auto path = QFileDialog::getExistingDirectory(
0123         this,
0124         i18nc("@title:window", "Choose directory"),
0125         export_path().path(),
0126         QFileDialog::DontResolveSymlinks
0127     );
0128     if ( !path.isEmpty() )
0129         d->ui.input_path->setText(path);
0130 }