File indexing completed on 2025-01-05 04:01:16

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 "spritesheet_format.hpp"
0008 #include "model/assets/composition.hpp"
0009 
0010 #include <QImage>
0011 #include <QPainter>
0012 #include <QImageWriter>
0013 
0014 glaxnimate::io::Autoreg<glaxnimate::io::raster::SpritesheetFormat> glaxnimate::io::raster::SpritesheetFormat::autoreg;
0015 
0016 QStringList glaxnimate::io::raster::SpritesheetFormat::extensions() const
0017 {
0018     QStringList formats;
0019     formats << "png";
0020     for ( const auto& fmt : QImageWriter::supportedImageFormats() )
0021         if ( fmt != "jpg" && fmt != "svg" )
0022             formats << QString::fromUtf8(fmt);
0023     return formats;
0024 }
0025 
0026 std::unique_ptr<app::settings::SettingsGroup> glaxnimate::io::raster::SpritesheetFormat::save_settings(model::Composition* comp) const
0027 {
0028     int first_frame = comp->animation->first_frame.get();
0029     int last_frame = comp->animation->last_frame.get();
0030     int frames = last_frame - first_frame;
0031     return std::make_unique<app::settings::SettingsGroup>(app::settings::SettingList{
0032         app::settings::Setting("frame_width", i18n("Frame Width"), i18n("Width of each frame"), comp->width.get(), 1, 999'999),
0033         app::settings::Setting("frame_height", i18n("Frame Height"), i18n("Height of each frame"), comp->height.get(), 1, 999'999),
0034         app::settings::Setting("columns", i18n("Columns"), i18n("Number of columns in the sheet"), std::ceil(math::sqrt(frames)), 1, 64),
0035         app::settings::Setting("frame_step", i18n("Time Step"), i18n("By how much each rendered frame should increase time (in frames)"), 1, 1, 16),
0036     });
0037 }
0038 
0039 bool glaxnimate::io::raster::SpritesheetFormat::on_save(QIODevice& file, const QString& filename, model::Composition* comp, const QVariantMap& setting_values)
0040 {
0041     Q_UNUSED(filename);
0042 
0043     int frame_w = setting_values["frame_width"].toInt();
0044     int frame_h = setting_values["frame_height"].toInt();
0045     int columns = setting_values["columns"].toInt();
0046     int frame_step = setting_values["frame_step"].toInt();
0047 
0048     if ( frame_w <= 0 || frame_h <= 0 || columns <= 0 || frame_step <= 0 )
0049         return false;
0050 
0051     int first_frame = comp->animation->first_frame.get();
0052     int last_frame = comp->animation->last_frame.get();
0053     int frames = (last_frame - first_frame) / frame_step;
0054     int rows = frames / columns;
0055 
0056     qreal scale_x = qreal(frame_w) / comp->width.get();
0057     qreal scale_y = qreal(frame_h) / comp->height.get();
0058 
0059     QImage bmp(frame_w * columns, frame_h * rows, QImage::Format_ARGB32);
0060     QPainter painter(&bmp);
0061     for ( int i = first_frame; i <= last_frame; i += frame_step )
0062     {
0063         painter.save();
0064         painter.scale(scale_x, scale_y);
0065         painter.translate((i % columns) * frame_w, (i / columns) * frame_h);
0066         painter.setClipRect(0, 0, frame_w, frame_h);
0067         comp->paint(&painter, i, model::VisualNode::Render);
0068         painter.restore();
0069     }
0070 
0071     painter.end();
0072 
0073 
0074     QImageWriter writer(&file, {});
0075     writer.setOptimizedWrite(true);
0076     if ( writer.write(bmp) )
0077         return true;
0078 
0079     error(writer.errorString());
0080     return false;
0081 }
0082