1 /*
2 * mp3plot - Bitrate analysis tool
3 *
4 * Copyright (C) 2007, 2009 Toni Corvera
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 // $Id: gd_plotter.cc 1213 2009-04-24 20:18:17Z $
22
23 #include "../mp3_config.h" // Defines HAVE_GD / DISABLE_GD / DISABLE_GRAPHICS
24
25 #if defined(HAVE_GD) && !defined(DISABLE_GRAPHICS) && !defined(DISABLE_GD)
26
27 #include <string>
28 #include <cassert>
29 #include <fstream>
30
31 #include "../common.h"
32 #include "../utils/logger.h"
33 #include "../mp3/bitrate.h"
34 #include "../mp3/frame.h"
35 #include "colour.h"
36 #include "gd_plotter.h"
37 #include "gd_image.h"
38
39 namespace {
40
41 using mp3plot::numframes_t;
42 using mp3plot::gd_image;
43 using mp3plot::graphics_lib_interface;
44
45 namespace gd = mp3plot::gdlib;
46
47 // This is pretty much redundant...
48 struct gd_interface : public graphics_lib_interface<gd::image, gd::colour> {
gd_interface__anonbe3f2ef10111::gd_interface49 gd_interface()
50 : cached_bordercol(0)
51 {}
52
~gd_interface__anonbe3f2ef10111::gd_interface53 virtual ~gd_interface() {
54 delete cached_bordercol;
55 }
create_image__anonbe3f2ef10111::gd_interface56 virtual image_type create_image(int w, int h) const {
57 return gd_image(w, h, gd::rgb24b_colour(0xff));
58 }
59
resize__anonbe3f2ef10111::gd_interface60 virtual void resize(image_type & im, int w, int h) const {
61 im.resize(w, h);
62 }
63
vertical_merge__anonbe3f2ef10111::gd_interface64 virtual image_type vertical_merge(const image_type& top, const image_type& bottom) const {
65 return gd_image::vmerge(top, bottom);
66 }
67
allocate_colour__anonbe3f2ef10111::gd_interface68 virtual native_colour allocate_colour(image_type& im,
69 const common_colour& c) const {
70 return im.allocate_colour(c);
71 }
72
draw_line__anonbe3f2ef10111::gd_interface73 virtual void draw_line(image_type & im,
74 int x0, int y0, int x1, int y1,
75 const native_colour & c) const
76 {
77 im.line(x0, y0, x1, y1, c);
78 }
79
draw_rectangle__anonbe3f2ef10111::gd_interface80 virtual void draw_rectangle(image_type& im,
81 int x0, int y0, int x1, int y1,
82 const native_colour& c) const
83 {
84 // Order is not important:
85 //assert( x0 < x1 );
86 //assert( y0 < y1 );
87 // Empty rectangle:
88 if (x0 == x1 && y0 == y1) { return; }
89 // "negative" rectangle
90 if (x0+1 >= x1-1 || y0+1 >= y1-1) { return; }
91
92 if (0 != cached_bordercol) {
93 if (cached_bordercol->first != &im) {
94 delete cached_bordercol;
95 cached_bordercol = 0;
96 }
97 }
98 if (0 == cached_bordercol) {
99 const int col = im.allocate_colour(gd::rgb24b_colour(0));
100 cached_bordercol = new std::pair<gd_image*,int>(&im, col);
101 }
102 assert( 0 != cached_bordercol );
103 assert( &im == cached_bordercol->first );
104 const int black = cached_bordercol->second;
105 im.rectangle(x0, y0, x1, y1, black, false);
106 im.rectangle(x0+1, y0+1, x1-1, y1-1, c, true);
107 }
108
109 // In GD, the coordinates are those of the top-left corner
draw_text__anonbe3f2ef10111::gd_interface110 virtual void draw_text(image_type& im,
111 int x, int y,
112 const native_colour & c,
113 const std::string & label) const
114 {
115 const int tw = im.get_font_width() * label.length();
116 im.text(x-(tw/2), y-(im.get_font_height()/2), c, label);
117 }
118 private:
119 mutable std::pair<gd_image*, int> * cached_bordercol;
120 };
121
122 } // anonymous namespace
123
124 namespace mp3plot {
125
plot(const mp3file & file,const plot_params & params) const126 void gd_plotter::plot(const mp3file & file, const plot_params& params) const
127 throw (e_error)
128 {
129 assert( !params.output_filename.empty() );
130
131 using namespace std;
132 net_outlyer::logger::os() << "Using the GD output module\n";
133
134 try {
135 const gd_image im = image_plotter::plot<gdlib::image, gdlib::colour>(file.get_frames(), gd_interface(), params);
136 std::ofstream ofs( params.output_filename.c_str(), ios::out|ios::binary );
137 ofs << im;
138 ofs.close();
139 }
140 catch (const e_error & e) {
141 // Only gd_image() throws
142 throw e_error("Failed to create images in memory.", EX_UNAVAILABLE);
143 }
144 } // gd_plotter::plot()
145
146
147 } // namespace mp3plot
148
149 #endif // DISABLE_GRAPHICS, DISABLE_GD
150
151 // vim:set ts=4 et ai:
152
153