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 }