Skip to content

Commit

Permalink
feat: add Magick++ as possible importer too
Browse files Browse the repository at this point in the history
Suggested in discussion of synfig#2795
synfig#2795 (comment)

to allow SVG import in .lst files, without imagemagick module
  • Loading branch information
rodolforg committed Jan 30, 2024
1 parent a80fae9 commit f79f2d1
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 1 deletion.
2 changes: 2 additions & 0 deletions synfig-core/po/POTFILES.in
Expand Up @@ -124,6 +124,8 @@ src/modules/mod_libavcodec/mptr.h
src/modules/mod_libavcodec/trgt_av.cpp
src/modules/mod_libavcodec/trgt_av.h
src/modules/mod_magickpp/main.cpp
src/modules/mod_magickpp/mptr_magickpp.cpp
src/modules/mod_magickpp/mptr_magickpp.h
src/modules/mod_magickpp/trgt_magickpp.cpp
src/modules/mod_magickpp/trgt_magickpp.h
src/modules/mod_mng/main.cpp
Expand Down
1 change: 1 addition & 0 deletions synfig-core/src/modules/mod_magickpp/CMakeLists.txt
@@ -1,5 +1,6 @@
add_library(mod_magickpp MODULE
"${CMAKE_CURRENT_LIST_DIR}/main.cpp"
"${CMAKE_CURRENT_LIST_DIR}/mptr_magickpp.cpp"
"${CMAKE_CURRENT_LIST_DIR}/trgt_magickpp.cpp"
)

Expand Down
2 changes: 2 additions & 0 deletions synfig-core/src/modules/mod_magickpp/Makefile.am
Expand Up @@ -18,6 +18,8 @@ module_LTLIBRARIES = libmod_magickpp.la

libmod_magickpp_la_SOURCES = \
main.cpp \
mptr_magickpp.cpp \
mpte_magickpp.h \
trgt_magickpp.cpp \
trgt_magickpp.h

Expand Down
36 changes: 35 additions & 1 deletion synfig-core/src/modules/mod_magickpp/main.cpp
Expand Up @@ -4,6 +4,7 @@
**
** \legal
** Copyright (c) 2007, 2008 Chris Moore
** Copyright (c) 2024 Synfig Contributors
**
** This file is part of Synfig.
**
Expand Down Expand Up @@ -37,6 +38,7 @@
#include <synfig/general.h>

#include <synfig/module.h>
#include "mptr_magickpp.h"
#include "trgt_magickpp.h"
#endif

Expand All @@ -46,7 +48,7 @@ MODULE_DESC_BEGIN(mod_magickpp)
MODULE_NAME("Magick++ Module (libMagick++)")
MODULE_DESCRIPTION("Provides an animated GIF target")
MODULE_AUTHOR("Chris Moore")
MODULE_VERSION("1.0")
MODULE_VERSION("2.0")
MODULE_COPYRIGHT(SYNFIG_COPYRIGHT)
MODULE_DESC_END

Expand Down Expand Up @@ -216,4 +218,36 @@ MODULE_INVENTORY_BEGIN(mod_magickpp)
TARGET_EXT(magickpp_trgt, "ycbcra")
TARGET_EXT(magickpp_trgt, "yuv")
END_TARGETS

BEGIN_IMPORTERS
IMPORTER_EXT(magickpp_mptr,"jpg")
IMPORTER_EXT(magickpp_mptr,"jpeg")
IMPORTER_EXT(magickpp_mptr,"png")
IMPORTER_EXT(magickpp_mptr,"bmp")
IMPORTER_EXT(magickpp_mptr,"gif")
IMPORTER_EXT(magickpp_mptr,"pcx")
IMPORTER_EXT(magickpp_mptr,"tif")
IMPORTER_EXT(magickpp_mptr,"tiff")
IMPORTER_EXT(magickpp_mptr,"tga")
IMPORTER_EXT(magickpp_mptr,"ps")
IMPORTER_EXT(magickpp_mptr,"pdf")
IMPORTER_EXT(magickpp_mptr,"pgm")
IMPORTER_EXT(magickpp_mptr,"psd")
IMPORTER_EXT(magickpp_mptr,"xcf")
IMPORTER_EXT(magickpp_mptr,"svg")
IMPORTER_EXT(magickpp_mptr,"tim")
IMPORTER_EXT(magickpp_mptr,"xpm")
IMPORTER_EXT(magickpp_mptr,"miff")
IMPORTER_EXT(magickpp_mptr,"ico")
IMPORTER_EXT(magickpp_mptr,"eps")
IMPORTER_EXT(magickpp_mptr,"ttf")
IMPORTER_EXT(magickpp_mptr,"pix")
IMPORTER_EXT(magickpp_mptr,"rla")
IMPORTER_EXT(magickpp_mptr,"mat")
IMPORTER_EXT(magickpp_mptr,"html")
IMPORTER_EXT(magickpp_mptr,"ept")
IMPORTER_EXT(magickpp_mptr,"dcm")
IMPORTER_EXT(magickpp_mptr,"fig")
IMPORTER_EXT(magickpp_mptr,"webp")
END_IMPORTERS
MODULE_INVENTORY_END
164 changes: 164 additions & 0 deletions synfig-core/src/modules/mod_magickpp/mptr_magickpp.cpp
@@ -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;
}
72 changes: 72 additions & 0 deletions synfig-core/src/modules/mod_magickpp/mptr_magickpp.h
@@ -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

0 comments on commit f79f2d1

Please sign in to comment.