Added new module 'mod_magickpp' for rendering multiple images to a single file using...
[synfig.git] / synfig-core / trunk / src / modules / mod_magickpp / trgt_magickpp.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file trgt_magickpp.cpp
3 **      \brief Magick++ Target Module
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright 2007 Chris Moore
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 **
21 ** === N O T E S ===========================================================
22 **
23 ** ========================================================================= */
24
25 /* === H E A D E R S ======================================================= */
26
27 #define SYNFIG_TARGET
28
29 #ifdef USING_PCH
30 #       include "pch.h"
31 #else
32 #ifdef HAVE_CONFIG_H
33 #       include <config.h>
34 #endif
35
36 #include <ETL/misc>
37 #include "trgt_magickpp.h"
38
39 #endif
40
41 /* === M A C R O S ========================================================= */
42
43 using namespace synfig;
44 using namespace std;
45 using namespace etl;
46
47 /* === G L O B A L S ======================================================= */
48
49 SYNFIG_TARGET_INIT(magickpp_trgt);
50 SYNFIG_TARGET_SET_NAME(magickpp_trgt,"magick++");
51 SYNFIG_TARGET_SET_EXT(magickpp_trgt,"gif");
52 SYNFIG_TARGET_SET_VERSION(magickpp_trgt,"0.1");
53 SYNFIG_TARGET_SET_CVS_ID(magickpp_trgt,"$Id$");
54
55 /* === M E T H O D S ======================================================= */
56
57 magickpp_trgt::~magickpp_trgt()
58 {
59         MagickLib::ExceptionInfo exceptionInfo;
60         MagickLib::GetExceptionInfo(&exceptionInfo);
61
62         // check whether this file format supports multiple-image files
63         Magick::Image image(*(images.begin()));
64         image.fileName(filename);
65         SetImageInfo(image.imageInfo(),Magick::MagickTrue,&exceptionInfo);
66
67         // the file type is now in image.imageInfo()->magick and
68         // image.adjoin() tells us whether we can write to a single file
69         if (image.adjoin())
70         {
71                 unsigned int delay = round_to_int(100.0 / desc.get_frame_rate());
72                 for_each(images.begin(), images.end(), Magick::animationDelayImage(delay));
73
74                 // if we can write multiple images to a single file, optimize
75                 // the images (only write the pixels that change from frame to
76                 // frame
77 #ifdef HAVE_MAGICK_OPTIMIZE
78                 linkImages(images.begin(), images.end());
79                 OptimizeImageTransparency(images.begin()->image(),&exceptionInfo);
80                 unlinkImages(images.begin(), images.end());
81 #else
82                 // linkImages(images.begin(), images.end());
83                 // MagickLib::Image* new_images = DeconstructImages(images.begin()->image(),&exceptionInfo);
84                 // unlinkImages(images.begin(), images.end());
85                 // images.clear();
86                 // insertImages(&images, new_images);
87 #endif
88         }
89         else
90                 // if we can't write multiple images to a file of this type,
91                 // include '%04d' in the filename, so the files will be numbered
92                 // with a fixed width, '0'-padded number
93                 filename = (filename_sans_extension(filename) + ".%04d" + filename_extension(filename));
94
95         Magick::writeImages(images.begin(), images.end(), filename);
96
97         if (buffer != NULL) delete [] buffer;
98         if (color_buffer != NULL) delete [] color_buffer;
99 }
100
101 bool
102 magickpp_trgt::set_rend_desc(RendDesc *given_desc)
103 {
104         desc = *given_desc;
105         return true;
106 }
107
108 bool
109 magickpp_trgt::init()
110 {
111         width = desc.get_w();
112         height = desc.get_h();
113
114         buffer = new unsigned char[4*width*height];
115         if (buffer == NULL)
116                 return false;
117
118         color_buffer = new Color[width];
119         if (color_buffer == NULL)
120         {
121                 delete [] buffer;
122                 return false;
123         }
124
125         return true;
126 }
127
128 void
129 magickpp_trgt::end_frame()
130 {
131         Magick::Image image(width, height, "RGBA", Magick::CharPixel, buffer);
132         images.push_back(image);
133 }
134
135 bool
136 magickpp_trgt::start_frame(synfig::ProgressCallback *callback)
137 {
138         row = 0;
139         return true;
140 }
141
142 Color*
143 magickpp_trgt::start_scanline(int scanline)
144 {
145         return color_buffer;
146 }
147
148 bool
149 magickpp_trgt::end_scanline()
150 {
151         convert_color_format(buffer + row++ * width*4, color_buffer, width, PF_RGB|PF_A, gamma());
152         return true;
153 }