Mercurial > hg > aimc
comparison trunk/src/Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.cc @ 411:a908972d234e
- Added support for movies!
author | tomwalters |
---|---|
date | Thu, 21 Oct 2010 01:46:39 +0000 |
parents | 7af493eb1563 |
children | 9c26f6532ea3 |
comparison
equal
deleted
inserted
replaced
410:7af493eb1563 | 411:a908972d234e |
---|---|
1 // Copyright 2007, Thomas Walters | 1 // Copyright 2007-2010, Thomas Walters, Willem van Engen |
2 // | 2 // |
3 // AIM-C: A C++ implementation of the Auditory Image Model | 3 // AIM-C: A C++ implementation of the Auditory Image Model |
4 // http://www.acousticscale.org/AIMC | 4 // http://www.acousticscale.org/AIMC |
5 // | 5 // |
6 // Licensed under the Apache License, Version 2.0 (the "License"); | 6 // Licensed under the Apache License, Version 2.0 (the "License"); |
30 #include <sys/stat.h> | 30 #include <sys/stat.h> |
31 #include <string.h> | 31 #include <string.h> |
32 #include <stdio.h> | 32 #include <stdio.h> |
33 #include <math.h> | 33 #include <math.h> |
34 | 34 |
35 #include "cairo-quartz.h" | |
36 | |
35 #include "Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.h" | 37 #include "Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.h" |
36 | 38 |
37 namespace aimc { | 39 namespace aimc { |
38 | 40 |
39 GraphicsOutputDeviceCairo::GraphicsOutputDeviceCairo(Parameters *pParam) | 41 GraphicsOutputDeviceCairo::GraphicsOutputDeviceCairo(Parameters *pParam) |
40 : GraphicsOutputDevice(pParam) { | 42 : GraphicsOutputDevice(pParam) { |
41 m_bOutputFile = false; | 43 m_bOutputFile = false; |
42 m_iFileNumber = 0; | 44 m_iFileNumber = 0; |
43 m_iVertexType = VertexTypeNone; | 45 m_iVertexType = VertexTypeNone; |
44 m_bUseMemoryBuffer=false; | 46 m_bUseMemoryBuffer=false; |
45 m_pParam->DefaultString("output.img.format", ".png"); | 47 parameters_->DefaultString("output.img.format", ".png"); |
46 } | 48 } |
47 | 49 |
48 bool GraphicsOutputDeviceCairo::Initialize(const char *sDir) { | 50 bool GraphicsOutputDeviceCairo::Initialize(string directory) { |
49 Init(); | 51 directory_ = directory; |
50 | 52 InititalzeInternal(); |
51 //! \todo Output to file if sDir is a file, to directory with | |
52 //! multiple images if it's a directory. | |
53 strncpy(m_sDir, sDir, sizeof(m_sDir)/sizeof(m_sDir[0])); | |
54 | 53 |
55 /* Try to open an image to see if everything is allright. We want to avoid | 54 /* Try to open an image to see if everything is allright. We want to avoid |
56 * errors in the main Process()ing loop. */ | 55 * errors in the main Process()ing loop. */ |
57 if ( !OpenFile(0) ) { | 56 /*if (!OpenFile(0)) { |
58 //! \todo Better error message that is more specific about the cause. | 57 //! \todo Better error message that is more specific about the cause. |
59 LOG_ERROR(_T("Could not open output directory '%s' using graphics format '%s'."), | 58 LOG_ERROR(_T("Could not open output directory '%s' using graphics format '%s'."), |
60 m_sDir, m_pParam->DefaultString("output.img.format", ".png") ); | 59 directory_.c_str(), parameters_->DefaultString("output.img.format", "png")); |
61 return false; | 60 return false; |
62 } | 61 } |
63 CloseFile(); | 62 CloseFile();*/ |
64 | 63 |
65 return true; | 64 return true; |
66 } | 65 } |
67 | 66 |
68 bool GraphicsOutputDeviceCairo::Initialize() { | 67 /*bool GraphicsOutputDeviceCairo::Initialize() { |
69 Init(); | 68 Init(); |
70 m_bUseMemoryBuffer = true; | 69 m_bUseMemoryBuffer = true; |
71 return(true); | 70 return(true); |
72 } | 71 }*/ |
73 | 72 |
74 void GraphicsOutputDeviceCairo::Init() { | 73 void GraphicsOutputDeviceCairo::InititalzeInternal() { |
75 AIM_ASSERT(m_pParam); | 74 AIM_ASSERT(parameters_); |
76 /* | 75 |
77 * Set parameters | 76 parameters_->DefaultString("output.img.color.background", "black"); |
78 */ | 77 |
79 m_pParam->GetString("output.img.color.background"); | 78 m_bInvertColors = parameters_->DefaultBool("output.img.color.invert", "false"); |
80 | 79 |
81 m_bInvertColors = m_pParam->GetBool("output.img.color.invert"); | 80 // Output size. |
82 | 81 m_iWidth = parameters_->DefaultInt("output.img.width", 800); |
83 // Output size! | 82 m_iHeight = parameters_->DefaultInt("output.img.height", 600); |
84 m_iWidth = m_pParam->GetUInt("output.img.width"); | 83 |
85 m_iHeight = m_pParam->GetUInt("output.img.height"); | 84 // Cairo's RGB24 format has 32-bit pixels with the upper 8 bits unused. |
85 // This is not the same as the plotutils PNG format. This information is transferred by the | |
86 // function GetPixelFormat. The pixel format is dealt with by the reciever. | |
87 m_cSurface = cairo_quartz_surface_create(CAIRO_FORMAT_RGB24, | |
88 m_iWidth, | |
89 m_iHeight); | |
90 m_cCr = cairo_create(m_cSurface); | |
91 cairo_scale(m_cCr, (float)m_iWidth, (float)m_iHeight); | |
92 // Now setup things for this plotter. | |
93 cairo_select_font_face(m_cCr, | |
94 parameters_->DefaultString("output.img.fontname", | |
95 "HersheySans"), | |
96 CAIRO_FONT_SLANT_NORMAL, | |
97 CAIRO_FONT_WEIGHT_BOLD); | |
98 cairo_set_font_size (m_cCr, 0.02); | |
86 } | 99 } |
87 | 100 |
88 unsigned char* GraphicsOutputDeviceCairo::GetBuffer() { | 101 unsigned char* GraphicsOutputDeviceCairo::GetBuffer() { |
89 if(m_bUseMemoryBuffer) | 102 if(m_bUseMemoryBuffer) |
90 return (cairo_image_surface_get_data (m_cSurface)); | 103 return (cairo_image_surface_get_data (m_cSurface)); |
91 else | 104 else |
92 return NULL; | 105 return NULL; |
93 } | 106 } |
94 | 107 |
95 bool GraphicsOutputDeviceCairo::OpenFile(unsigned int index) { | 108 bool GraphicsOutputDeviceCairo::OpenFile(unsigned int index) { |
96 const char *strPlottype = m_pParam->GetString("output.img.format"); | 109 const char *strPlottype = parameters_->GetString("output.img.format"); |
97 if (!m_bUseMemoryBuffer) { | 110 if (!m_bUseMemoryBuffer) { |
98 struct stat fileinfo; | 111 struct stat fileinfo; |
99 // Get filename without trailing slash | 112 // Get filename without trailing slash |
100 strncpy(m_sFilename, m_sDir, sizeof(m_sFilename)/sizeof(m_sFilename[0])); | 113 char filename[PATH_MAX]; |
114 strncpy(filename, directory_.c_str(), sizeof(filename)/sizeof(filename[0])); | |
101 #ifdef _WINDOWS | 115 #ifdef _WINDOWS |
102 if (m_sFilename[strlen(m_sFilename)-1]=='\\') { | 116 if (filename[strlen(filename)-1]=='\\') { |
103 m_sFilename[strlen(m_sFilename)-1]='\0'; | 117 filename[strlen(filename)-1]='\0'; |
104 } | 118 } |
105 #else | 119 #else |
106 if (m_sFilename[strlen(m_sFilename)-1]=='/') { | 120 if (filename[strlen(filename)-1]=='/') { |
107 m_sFilename[strlen(m_sFilename)-1]='\0'; | 121 filename[strlen(filename)-1]='\0'; |
108 } | 122 } |
109 #endif | 123 #endif |
110 // Enumerate files it m_sDir is a directory. | 124 // Enumerate files it m_sDir is a directory. |
111 if (stat(m_sFilename, &fileinfo) == 0 && (fileinfo.st_mode & S_IFDIR)) { | 125 if (stat(filename, &fileinfo) == 0 && (fileinfo.st_mode & S_IFDIR)) { |
112 // We have a directory: enumerate with index | 126 // We have a directory: enumerate with index |
113 snprintf(m_sFilename, sizeof(m_sFilename)/sizeof(m_sFilename[0]),"%s%06d.%s", | 127 snprintf(filename, sizeof(filename) / sizeof(filename[0]), |
114 m_sDir, | 128 "%s%06d.%s", |
129 directory_.c_str(), | |
115 index, | 130 index, |
116 strPlottype); | 131 strPlottype); |
117 // If type is 'auto', fallback to 'png' | 132 // If type is 'auto', fallback to 'png' |
118 if (strcmp(strPlottype, "auto")==0) | 133 if (strcmp(strPlottype, "auto")==0) |
119 strPlottype = "png"; | 134 strPlottype = "png"; |
120 } else { | 135 } else { |
121 // We have a (probably non-existant) file. Auto-detect type by extension if requested | 136 // We have a (probably non-existant) file. Auto-detect type by extension if requested |
122 strncpy(m_sFilename, m_sDir, sizeof(m_sFilename)/sizeof(m_sFilename[0])); | 137 strncpy(filename, |
123 char *pDot = strrchr(m_sFilename, '.'); | 138 directory_.c_str(), |
139 sizeof(filename)/sizeof(filename[0])); | |
140 char *pDot = strrchr(filename, '.'); | |
124 if (!pDot) { | 141 if (!pDot) { |
125 LOG_ERROR(_T("Please supply extension on filename when using 'auto' format: '%s'"), | 142 LOG_ERROR(_T("Please supply extension on filename when using 'auto' format: '%s'"), |
126 m_sFilename); | 143 filename); |
127 return false; | 144 return false; |
128 } | 145 } |
129 strPlottype = &pDot[1]; | 146 strPlottype = &pDot[1]; |
130 } | 147 } |
148 image_filename_ = filename; | |
131 m_bOutputFile= true; //! \todo Should check that it's possible to write to the file | 149 m_bOutputFile= true; //! \todo Should check that it's possible to write to the file |
132 } | 150 } |
133 // Cairo's RGB24 format has 32-bit pixels with the upper 8 bits unused. | 151 |
134 // This is not the same as the plotutils PNG format. This information is transferred by the | |
135 // function GetPixelFormat. The pixel format is dealt with by the reciever. | |
136 m_cSurface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, | |
137 m_iWidth, | |
138 m_iHeight); | |
139 m_cCr = cairo_create (m_cSurface); | |
140 cairo_scale(m_cCr, (float)m_iWidth, (float)m_iHeight); | |
141 // Now setup things for this plotter. | |
142 cairo_select_font_face(m_cCr, | |
143 m_pParam->GetString("output.img.fontname"), | |
144 CAIRO_FONT_SLANT_NORMAL, | |
145 CAIRO_FONT_WEIGHT_BOLD); | |
146 cairo_set_font_size (m_cCr, 0.015); | |
147 return true; | 152 return true; |
148 } | 153 } |
149 | 154 |
150 void GraphicsOutputDeviceCairo::CloseFile() { | 155 void GraphicsOutputDeviceCairo::CloseFile() { |
151 // Plotting library | |
152 if (m_iPlotHandle>0) { | |
153 cairo_destroy(m_cCr); | |
154 m_iPlotHandle = 0; | |
155 } | |
156 // And the output file | 156 // And the output file |
157 if (m_bOutputFile) { | 157 if (m_bOutputFile) { |
158 cairo_surface_write_to_png(m_cSurface, m_sFilename); | 158 cairo_surface_write_to_png(m_cSurface, image_filename_.c_str()); |
159 m_bOutputFile = false; | 159 m_bOutputFile = false; |
160 } | 160 } |
161 cairo_surface_destroy(m_cSurface); | 161 cairo_set_source_rgb (m_cCr, 0.0, 0.0, 0.0); |
162 cairo_paint (m_cCr); | |
163 //cairo_destroy(m_cCr); | |
164 //cairo_surface_destroy(m_cSurface); | |
162 } | 165 } |
163 | 166 |
164 GraphicsOutputDeviceCairo::~GraphicsOutputDeviceCairo() { | 167 GraphicsOutputDeviceCairo::~GraphicsOutputDeviceCairo() { |
165 AIM_ASSERT(!m_iPlotHandle); | 168 AIM_ASSERT(!m_iPlotHandle); |
166 CloseFile(); | 169 CloseFile(); |
196 cairo_set_line_width (m_cCr, 0.001f); | 199 cairo_set_line_width (m_cCr, 0.001f); |
197 } | 200 } |
198 | 201 |
199 void GraphicsOutputDeviceCairo::gColor3f(float r, float g, float b) { | 202 void GraphicsOutputDeviceCairo::gColor3f(float r, float g, float b) { |
200 if (m_bInvertColors) { | 203 if (m_bInvertColors) { |
201 r = 1-r; | 204 r = 1.0 - r; |
202 g = 1-g; | 205 g = 1.0 - g; |
203 b = 1-b; | 206 b = 1.0 - b; |
204 } | 207 } |
205 cairo_set_source_rgb (m_cCr, r, g, b); | 208 cairo_set_source_rgb (m_cCr, r, g, b); |
206 } | 209 } |
207 | 210 |
208 void GraphicsOutputDeviceCairo::gVertex3f(float x, float y, float z) { | 211 void GraphicsOutputDeviceCairo::gVertex3f(float x, float y, float z) { |
209 switch(m_iVertexType) { | 212 switch(m_iVertexType) { |
210 case VertexTypeLine: | 213 case VertexTypeLine: |
211 if (m_bIsFirstVertex) { | 214 if (m_bIsFirstVertex) { |
212 m_bIsFirstVertex = false; | 215 m_bIsFirstVertex = false; |
213 //pl_fmove(x, y); | 216 //pl_fmove(x, y); |
214 cairo_move_to(m_cCr, x, 1-y); | 217 cairo_move_to(m_cCr, x, 1.0 - y); |
215 } else { | 218 } else { |
216 //pl_fcont(x, y); | 219 //pl_fcont(x, y); |
217 cairo_line_to(m_cCr, x, 1-y); | 220 cairo_line_to(m_cCr, x, 1.0 - y); |
218 } | 221 } |
219 break; | 222 break; |
220 case VertexTypeQuad: | 223 case VertexTypeQuad: |
221 /* Store vertices until we got four in a row. | 224 /* Store vertices until we have four in a row. |
222 * The order of vertices when processing quads is: | 225 * The order of vertices when processing quads is: |
223 * 1-----3-----5 | 226 * 1-----3-----5 |
224 * | | | | 227 * | | | |
225 * 0-----2-----4 | 228 * 0-----2-----4 |
226 */ | 229 */ |
227 if (m_iPrevVertexCount >= 3) { | 230 if (m_iPrevVertexCount >= 3) { |
228 // Plot this quad | 231 // Plot this quad |
229 cairo_move_to(m_cCr, m_aPrevX[0], 1-m_aPrevY[0]); | 232 //cairo_set_source_rgb(m_cCr, 0.2, 1 - m_aPrevY[0], m_aPrevX[0]); |
230 cairo_line_to(m_cCr, m_aPrevX[1], 1-m_aPrevY[1]); | 233 cairo_rectangle (m_cCr, m_aPrevX[2], |
234 1 - m_aPrevY[2], m_aPrevX[2] - m_aPrevX[0], | |
235 y - m_aPrevY[2]); | |
236 cairo_fill (m_cCr); | |
237 | |
238 /*cairo_move_to(m_cCr, , ); | |
239 cairo_line_to(m_cCr, , 1 - m_aPrevY[1]); | |
231 cairo_line_to(m_cCr, x, y); | 240 cairo_line_to(m_cCr, x, y); |
232 cairo_line_to(m_cCr, m_aPrevX[2], 1-m_aPrevY[2]); | 241 cairo_line_to(m_cCr, m_aPrevX[2], 1 - m_aPrevY[2]);*/ |
233 cairo_close_path (m_cCr); | 242 |
234 | 243 |
235 // Last vertices of this quad are the first of the next | 244 // Last vertices of this quad are the first of the next |
236 m_aPrevX[0] = m_aPrevX[2]; | 245 m_aPrevX[0] = m_aPrevX[2]; |
237 m_aPrevY[0] = m_aPrevY[2]; | 246 m_aPrevY[0] = m_aPrevY[2]; |
238 m_aPrevX[1] = x; | 247 m_aPrevX[1] = x; |
265 const char *sStr, | 274 const char *sStr, |
266 bool bRotated) { | 275 bool bRotated) { |
267 //cairo_text_extents_t te; | 276 //cairo_text_extents_t te; |
268 if (bRotated) { | 277 if (bRotated) { |
269 cairo_rotate(m_cCr, M_PI/2); | 278 cairo_rotate(m_cCr, M_PI/2); |
270 cairo_move_to(m_cCr, x ,1-y); | 279 //cairo_move_to(m_cCr, x ,1-y); |
271 cairo_show_text(m_cCr, sStr); | 280 cairo_show_text(m_cCr, sStr); |
272 //cairo_identity_matrix(m_cCr); | 281 //cairo_identity_matrix(m_cCr); |
273 cairo_rotate(m_cCr, -M_PI/2); | 282 cairo_rotate(m_cCr, -M_PI/2); |
274 } else { | 283 } else { |
275 cairo_move_to(m_cCr, x ,1-y); | 284 cairo_move_to(m_cCr, x ,1-y); |