Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Magick++ as possible importer too #3323

Merged
merged 2 commits into from Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
177 changes: 177 additions & 0 deletions synfig-core/src/modules/mod_magickpp/mptr_magickpp.cpp
@@ -0,0 +1,177 @@
/* === 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);

image.type(Magick::TrueColorType);
// Sadly Magick++ API is a mess with namespaces...
{
using namespace Magick;
using namespace MagickCore;

#if MagickLibVersion >= 0x701 // MAGICKCORE_CHECK_VERSION(7,0,0) does not work!
bool has_alpha = image.alpha();
#else
bool has_alpha = image.matte();
#endif
const auto packet = image.getConstPixels(0, 0, width, height);

if (!packet) {
synfig::error(_("Magick++ importer: couldn't get pixel packet"));
return false;
}

constexpr synfig::Color::value_type factor = QuantumRange;

for (size_t y = 0, i = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x, ++i) {
#if MagickLibVersion >= 0x701 // MAGICKCORE_CHECK_VERSION(7,0,0) does not work!
if (has_alpha)
surface[y][x] = synfig::Color(packet[i++] / factor, packet[i++] / factor, packet[i++] / factor, packet[i] / factor);
else
surface[y][x] = synfig::Color(packet[i++] / factor, packet[i++] / factor, packet[i] / factor, 1.);
#else
const auto& color = packet[i];
if (has_alpha)
surface[y][x] = synfig::Color(color.red / factor, color.green / factor, color.blue / factor, 1. - color.opacity / factor);
else
surface[y][x] = synfig::Color(color.red / factor, color.green / factor, color.blue / factor, 1.);
#endif
}
}
} // end Magick++ namespace mess
} 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