forked from synfig/synfig
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add Magick++ as possible importer too
Suggested in discussion of synfig#2795 synfig#2795 (comment) to allow SVG import in .lst files, without imagemagick module
- Loading branch information
Showing
6 changed files
with
276 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
/* === S Y N F I G ========================================================= */ | ||
/*! \file mptr_magickpp.cpp | ||
** \brief Magick++ Importer (magickpp_mptr) | ||
** | ||
** \legal | ||
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley | ||
** Copyright (c) 2024 Synfig Contributors | ||
** | ||
** This file is part of Synfig. | ||
** | ||
** Synfig is free software: you can redistribute it and/or modify | ||
** it under the terms of the GNU General Public License as published by | ||
** the Free Software Foundation, either version 2 of the License, or | ||
** (at your option) any later version. | ||
** | ||
** Synfig is distributed in the hope that it will be useful, | ||
** but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
** GNU General Public License for more details. | ||
** | ||
** You should have received a copy of the GNU General Public License | ||
** along with Synfig. If not, see <https://www.gnu.org/licenses/>. | ||
** \endlegal | ||
** | ||
** ========================================================================= */ | ||
|
||
/* === H E A D E R S ======================================================= */ | ||
|
||
#ifdef USING_PCH | ||
# include "pch.h" | ||
#else | ||
#ifdef HAVE_CONFIG_H | ||
# include <config.h> | ||
#endif | ||
|
||
#include "mptr_magickpp.h" | ||
|
||
#include <synfig/general.h> | ||
#include <synfig/localization.h> | ||
#include <synfig/os.h> | ||
|
||
#include <Magick++.h> | ||
|
||
#endif | ||
|
||
/* === M A C R O S ========================================================= */ | ||
|
||
using namespace synfig; | ||
|
||
/* === G L O B A L S ======================================================= */ | ||
|
||
SYNFIG_IMPORTER_INIT(magickpp_mptr); | ||
SYNFIG_IMPORTER_SET_NAME(magickpp_mptr,"magick++"); | ||
SYNFIG_IMPORTER_SET_EXT(magickpp_mptr,"svg"); | ||
SYNFIG_IMPORTER_SET_VERSION(magickpp_mptr,"0.1"); | ||
SYNFIG_IMPORTER_SET_SUPPORTS_FILE_SYSTEM_WRAPPER(magickpp_mptr, false); | ||
|
||
/* === M E T H O D S ======================================================= */ | ||
|
||
magickpp_mptr::magickpp_mptr(const synfig::FileSystem::Identifier& identifier) | ||
: synfig::Importer(identifier), animation_repetitions_(0) | ||
{ | ||
Magick::InitializeMagick(synfig::OS::get_binary_path().u8_str()); | ||
|
||
try { | ||
std::string filename = identifier.file_system->get_real_filename(identifier.filename.u8string()); | ||
Magick::Image image; | ||
image.ping(filename+"[-1]"); | ||
auto n_frames = image.scene() + 1; | ||
if (n_frames <= 1) { | ||
animation_repetitions_ = 0; | ||
} else { | ||
frame_time_list_.resize(n_frames); | ||
synfig::Time current_time; | ||
for (size_t i = 0; i < n_frames; ++i) { | ||
image.ping(strprintf("%s[%zu]", filename.c_str(), i)); | ||
frame_time_list_[i] = current_time; | ||
current_time += image.animationDelay() * 0.01; // The delay is in multiple of 10ms | ||
} | ||
animation_length_ = current_time; | ||
animation_repetitions_ = image.animationIterations(); | ||
} | ||
} catch (Magick::Error& err) { | ||
// because 'Error' is derived from the standard C++ exception, it has a 'what()' method | ||
synfig::error(_("Magick++ importer: error occurred reading a file: %s"), err.what()); | ||
} catch (...) { | ||
synfig::error(_("Magick++ importer: an unhandled error has occurred on reading file %s"), identifier.filename.u8_str()); | ||
} | ||
} | ||
|
||
magickpp_mptr::~magickpp_mptr() | ||
{ | ||
} | ||
|
||
bool | ||
magickpp_mptr::is_animated() | ||
{ | ||
return frame_time_list_.size() > 0; | ||
} | ||
|
||
bool | ||
magickpp_mptr::get_frame(synfig::Surface& surface, const synfig::RendDesc& /*renddesc*/, synfig::Time time, synfig::ProgressCallback* /*callback*/) | ||
{ | ||
const std::string filename = identifier.file_system->get_real_filename(identifier.filename.u8string()); | ||
|
||
try { | ||
Magick::Image image; | ||
if (!is_animated()) { | ||
image.read(filename); | ||
} else { | ||
int repetition_n = 0; | ||
while (time >= animation_length_) { | ||
++repetition_n; | ||
time -= animation_length_; | ||
} | ||
|
||
auto frame_index = frame_time_list_.size() - 1; | ||
if (animation_repetitions_ == 0 || repetition_n < animation_repetitions_) { | ||
for (frame_index = frame_time_list_.size() - 1; frame_index > 0; --frame_index) { | ||
if (time >= frame_time_list_[frame_index]) | ||
break; | ||
} | ||
} | ||
|
||
image.read(strprintf("%s[%zu]", filename.c_str(), frame_index)); | ||
} | ||
const auto width = image.size().width(); | ||
const auto height = image.size().height(); | ||
surface.set_wh(width, height); | ||
|
||
const Magick::PixelPacket* packet = image.getConstPixels(0, 0, width, height); | ||
if (!packet) { | ||
synfig::error(_("Magick++ importer: couldn't get pixel packet")); | ||
return false; | ||
} | ||
|
||
// Sadly ImageMagick is a mess with this QuantumRange macro - it needs Magick namespace in its parsing... | ||
// constexpr synfig::Color::value_type factor = 1. / QuantumRange; | ||
// alternative way: | ||
synfig::Color::value_type factor = 1.; | ||
{ | ||
using namespace Magick; | ||
|
||
factor = QuantumRange; | ||
} | ||
|
||
for (size_t y = 0, i = 0; y < height; ++y) { | ||
for (size_t x = 0; x < width; ++x, ++i) { | ||
const auto& color = packet[i]; | ||
auto surface_color = synfig::Color(color.red / factor, color.green / factor, color.blue / factor, 1. - color.opacity / factor); | ||
|
||
surface[y][x] = surface_color; | ||
} | ||
} | ||
} catch (Magick::Error& err) { | ||
synfig::error(_("Magick++ importer: error occurred fetching pixels: %s"), err.what()); | ||
return false; | ||
} catch (...) { | ||
synfig::error(_("Magick++ importer: an unhandled error has occurred on fetching pixels from file %s"), identifier.filename.u8_str()); | ||
return false; | ||
} | ||
|
||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* === S Y N F I G ========================================================= */ | ||
/*! \file mptr_magickpp.h | ||
** \brief Header for Magick++ Importer (magickpp_mptr) | ||
** | ||
** \legal | ||
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley | ||
** Copyright (c) 2024 Synfig Contributors | ||
** | ||
** This file is part of Synfig. | ||
** | ||
** Synfig is free software: you can redistribute it and/or modify | ||
** it under the terms of the GNU General Public License as published by | ||
** the Free Software Foundation, either version 2 of the License, or | ||
** (at your option) any later version. | ||
** | ||
** Synfig is distributed in the hope that it will be useful, | ||
** but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
** GNU General Public License for more details. | ||
** | ||
** You should have received a copy of the GNU General Public License | ||
** along with Synfig. If not, see <https://www.gnu.org/licenses/>. | ||
** \endlegal | ||
** | ||
** ========================================================================= */ | ||
|
||
/* === S T A R T =========================================================== */ | ||
|
||
#ifndef SYNFIG_MPTR_MAGICKPP_H | ||
#define SYNFIG_MPTR_MAGICKPP_H | ||
|
||
/* === H E A D E R S ======================================================= */ | ||
|
||
#include <synfig/importer.h> | ||
#include <synfig/surface.h> | ||
|
||
/* === M A C R O S ========================================================= */ | ||
|
||
/* === T Y P E D E F S ===================================================== */ | ||
|
||
/* === C L A S S E S & S T R U C T S ======================================= */ | ||
|
||
/** | ||
* Import static images, animated images or, possibly, videos | ||
* by using Magick++ library | ||
*/ | ||
class magickpp_mptr : public synfig::Importer | ||
{ | ||
SYNFIG_IMPORTER_MODULE_EXT | ||
|
||
public: | ||
magickpp_mptr(const synfig::FileSystem::Identifier& identifier); | ||
|
||
~magickpp_mptr(); | ||
|
||
bool is_animated() override; | ||
|
||
bool get_frame(synfig::Surface& surface, const synfig::RendDesc& renddesc, synfig::Time time, synfig::ProgressCallback* callback) override; | ||
|
||
private: | ||
// Info for animations | ||
/** number of repetitions. Zero means infinity */ | ||
ssize_t animation_repetitions_; | ||
/** Initial time of each frame */ | ||
std::vector<synfig::Time> frame_time_list_; | ||
/** Total duration of an animation cycle */ | ||
synfig::Time animation_length_; | ||
}; | ||
|
||
/* === E N D =============================================================== */ | ||
|
||
#endif |