tomwalters@397
|
1 // Copyright 2006, Willem van Engen
|
tomwalters@397
|
2 //
|
tomwalters@397
|
3 // AIM-C: A C++ implementation of the Auditory Image Model
|
tomwalters@397
|
4 // http://www.acousticscale.org/AIMC
|
tomwalters@397
|
5 //
|
tomwalters@397
|
6 // Licensed under the Apache License, Version 2.0 (the "License");
|
tomwalters@397
|
7 // you may not use this file except in compliance with the License.
|
tomwalters@397
|
8 // You may obtain a copy of the License at
|
tomwalters@397
|
9 //
|
tomwalters@397
|
10 // http://www.apache.org/licenses/LICENSE-2.0
|
tomwalters@397
|
11 //
|
tomwalters@397
|
12 // Unless required by applicable law or agreed to in writing, software
|
tomwalters@397
|
13 // distributed under the License is distributed on an "AS IS" BASIS,
|
tomwalters@397
|
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
tomwalters@397
|
15 // See the License for the specific language governing permissions and
|
tomwalters@397
|
16 // limitations under the License.
|
tomwalters@397
|
17
|
tomwalters@397
|
18 /*!
|
tomwalters@397
|
19 * \file
|
tomwalters@397
|
20 * \brief Output device for output to a graphics file using plotutils
|
tomwalters@397
|
21 *
|
tomwalters@397
|
22 * \author Willem van Engen <cnbh@willem.engen.nl>
|
tomwalters@397
|
23 * \date created 2006/10/13
|
tomwalters@397
|
24 * \version \$Id: GraphicsOutputDevicePlotutils.cpp 493 2007-11-27 10:59:20Z tom $
|
tomwalters@397
|
25 */
|
tomwalters@397
|
26 #include "Support/Common.h"
|
tomwalters@397
|
27
|
tomwalters@397
|
28 #include <sys/types.h>
|
tomwalters@397
|
29 #include <sys/stat.h>
|
tomwalters@397
|
30 #include <string.h>
|
tomwalters@397
|
31 #include <stdio.h>
|
tomwalters@397
|
32 #include <math.h>
|
tomwalters@397
|
33
|
tomwalters@397
|
34 #include "Support/util.h"
|
tomwalters@397
|
35 #include "Modules/Output/Graphics/Devices/GraphicsOutputDevicePlotutils.h"
|
tomwalters@397
|
36
|
tomwalters@397
|
37 GraphicsOutputDevicePlotutils::GraphicsOutputDevicePlotutils(Parameters *pParam)
|
tomwalters@397
|
38 : GraphicsOutputDevice(pParam) {
|
tomwalters@398
|
39 m_iPlotHandle = 0;
|
tomwalters@398
|
40 m_pOutputFile = NULL;
|
tomwalters@398
|
41 m_iFileNumber = 0;
|
tomwalters@398
|
42 m_iVertexType = VertexTypeNone;
|
tomwalters@398
|
43 m_bUseMemoryBuffer = false;
|
tomwalters@398
|
44 m_pMemoryBuffer = NULL;
|
tomwalters@398
|
45 m_uWidth=0;
|
tomwalters@398
|
46 m_uHeight=0;
|
tomwalters@397
|
47 }
|
tomwalters@397
|
48
|
tomwalters@397
|
49 bool GraphicsOutputDevicePlotutils::Initialize(const char *sDir) {
|
tomwalters@397
|
50 Init();
|
tomwalters@397
|
51
|
tomwalters@398
|
52 //! \todo Output to file if sDir is a file, to directory with multiple
|
tomwalters@397
|
53 //! images if it's a directory.
|
tomwalters@398
|
54 strncpy(m_sDir, sDir, sizeof(m_sDir)/sizeof(m_sDir[0]));
|
tomwalters@397
|
55
|
tomwalters@398
|
56 /* Try to open an image to see if everything is allright. We want to avoid
|
tomwalters@398
|
57 * errors in the main Process()ing loop. */
|
tomwalters@398
|
58 if (!OpenFile(0)) {
|
tomwalters@398
|
59 //! \todo Better error message that is more specific about the cause.
|
tomwalters@398
|
60 AIM_ERROR(_T("Could not open output directory '%s' using graphics format '%s'."),
|
tomwalters@398
|
61 m_sDir, m_pParam->GetString("output.img.format") );
|
tomwalters@398
|
62 return false;
|
tomwalters@398
|
63 }
|
tomwalters@398
|
64 CloseFile();
|
tomwalters@398
|
65 return true;
|
tomwalters@397
|
66 }
|
tomwalters@397
|
67
|
tomwalters@397
|
68 void GraphicsOutputDevicePlotutils::Init() {
|
tomwalters@397
|
69 AIM_ASSERT(m_pParam);
|
tomwalters@398
|
70 /*
|
tomwalters@398
|
71 * Set parameters
|
tomwalters@398
|
72 */
|
tomwalters@398
|
73 pl_parampl("BG_COLOR", (void*)m_pParam->GetString("output.img.color.background"));
|
tomwalters@398
|
74 // Handle GIFs as other output formats, don't merge frames into single GIF.
|
tomwalters@398
|
75 pl_parampl("GIF_ANIMATION", (void*)"no");
|
tomwalters@398
|
76 pl_parampl("INTERLACE", (void*)"no");
|
tomwalters@397
|
77
|
tomwalters@398
|
78 m_bInvertColors = m_pParam->GetBool("output.img.color.invert");
|
tomwalters@397
|
79
|
tomwalters@398
|
80 // Output size!
|
tomwalters@398
|
81 m_uWidth = m_pParam->GetUInt("output.img.width");
|
tomwalters@398
|
82 m_uHeight = m_pParam->GetUInt("output.img.height");
|
tomwalters@398
|
83 char strSize[100];
|
tomwalters@398
|
84 snprintf(strSize, sizeof(strSize)/sizeof(strSize[0]), "%ux%u", m_uWidth, m_uHeight);
|
tomwalters@398
|
85 pl_parampl("BITMAPSIZE", (void*)strSize);
|
tomwalters@397
|
86 }
|
tomwalters@397
|
87
|
tomwalters@397
|
88 bool GraphicsOutputDevicePlotutils::Initialize() {
|
tomwalters@397
|
89 Init();
|
tomwalters@397
|
90 m_bUseMemoryBuffer = true;
|
tomwalters@397
|
91 return(true);
|
tomwalters@397
|
92 }
|
tomwalters@397
|
93
|
tomwalters@397
|
94 bool GraphicsOutputDevicePlotutils::OpenFile(unsigned int index) {
|
tomwalters@397
|
95 const char *strPlottype = m_pParam->GetString("output.img.format");
|
tomwalters@397
|
96 if (!m_bUseMemoryBuffer) {
|
tomwalters@397
|
97 char sFilename[PATH_MAX];
|
tomwalters@397
|
98 struct stat fileinfo;
|
tomwalters@397
|
99
|
tomwalters@397
|
100 // Get filename without trailing slash
|
tomwalters@397
|
101 strncpy(sFilename, m_sDir, sizeof(sFilename)/sizeof(sFilename[0]));
|
tomwalters@397
|
102 #ifdef _WINDOWS
|
tomwalters@397
|
103 if (sFilename[strlen(sFilename)-1]=='\\') {
|
tomwalters@397
|
104 sFilename[strlen(sFilename)-1]='\0';
|
tomwalters@397
|
105 }
|
tomwalters@397
|
106 #else
|
tomwalters@397
|
107 if (sFilename[strlen(sFilename)-1]=='/') {
|
tomwalters@397
|
108 sFilename[strlen(sFilename)-1]='\0';
|
tomwalters@397
|
109 }
|
tomwalters@397
|
110 #endif
|
tomwalters@397
|
111 // Enumerate files it m_sDir is a directory.
|
tomwalters@397
|
112 if ( stat(sFilename, &fileinfo)==0 && (fileinfo.st_mode & S_IFDIR) ) {
|
tomwalters@397
|
113 // We have a directory: enumerate with index
|
tomwalters@397
|
114 snprintf(sFilename, sizeof(sFilename)/sizeof(sFilename[0]),"%s%06d.%s", m_sDir, index, strPlottype);
|
tomwalters@397
|
115 // If type is 'auto', fallback to 'png'
|
tomwalters@397
|
116 if (strcmp(strPlottype, "auto")==0)
|
tomwalters@397
|
117 strPlottype = "png";
|
tomwalters@397
|
118 } else {
|
tomwalters@397
|
119 // We have a (probabely non-existant) file. Auto-detect type by extension if requested
|
tomwalters@397
|
120 strncpy(sFilename, m_sDir, sizeof(sFilename)/sizeof(sFilename[0]));
|
tomwalters@397
|
121 char *pDot = strrchr(sFilename, '.');
|
tomwalters@397
|
122 if (!pDot) {
|
tomwalters@397
|
123 AIM_ERROR(_T("Please supply extension on filename when using 'auto' format: '%s'"), sFilename);
|
tomwalters@397
|
124 return false;
|
tomwalters@397
|
125 }
|
tomwalters@397
|
126 strPlottype = &pDot[1];
|
tomwalters@397
|
127 }
|
tomwalters@397
|
128 if ((m_pOutputFile = fopen(sFilename, "wb")) == NULL) {
|
tomwalters@397
|
129 return false;
|
tomwalters@397
|
130 }
|
tomwalters@397
|
131 } else {
|
tomwalters@397
|
132 #if !defined(_WINDOWS) && !defined(_MACOSX)
|
tomwalters@397
|
133 if ((m_pOutputFile=open_memstream(&m_pMemoryBuffer, &m_sMemoryBufferSize))==NULL)
|
tomwalters@397
|
134 #endif
|
tomwalters@397
|
135 return false;
|
tomwalters@397
|
136 strPlottype="pnm"; // Force pnm format or this doesn't work
|
tomwalters@397
|
137 }
|
tomwalters@397
|
138
|
tomwalters@398
|
139 /*
|
tomwalters@398
|
140 * Create a plotter
|
tomwalters@398
|
141 *
|
tomwalters@398
|
142 * Plotutils knows the following types for file output:
|
tomwalters@398
|
143 * pnm gif ai ps gif pcl hpgl tek meta
|
tomwalters@398
|
144 */
|
tomwalters@398
|
145 if ((m_iPlotHandle = pl_newpl(strPlottype,
|
tomwalters@397
|
146 NULL,
|
tomwalters@397
|
147 m_pOutputFile,
|
tomwalters@397
|
148 stderr)) < 0 ) {
|
tomwalters@398
|
149 return false;
|
tomwalters@398
|
150 }
|
tomwalters@398
|
151 pl_selectpl(m_iPlotHandle);
|
tomwalters@397
|
152
|
tomwalters@398
|
153 if ( pl_openpl() < 0) {
|
tomwalters@398
|
154 return false;
|
tomwalters@398
|
155 }
|
tomwalters@397
|
156
|
tomwalters@398
|
157 // Now setup things for this plotter
|
tomwalters@398
|
158 pl_fontname(m_pParam->GetString("output.img.fontname"));
|
tomwalters@398
|
159 //! \todo Make fontsize work in Plotutils, currently disabled
|
tomwalters@398
|
160 //pl_ffontsize(m_pParam->GetUInt("output.fontsize"));
|
tomwalters@397
|
161
|
tomwalters@398
|
162 return true;
|
tomwalters@397
|
163 }
|
tomwalters@397
|
164
|
tomwalters@397
|
165 char* GraphicsOutputDevicePlotutils::GetBuffer() {
|
tomwalters@397
|
166 if(m_bUseMemoryBuffer && (m_pMemoryBuffer!=NULL))
|
tomwalters@397
|
167 return (&m_pMemoryBuffer[m_sMemoryBufferSize-(m_uWidth*m_uHeight*3)]);
|
tomwalters@397
|
168 else
|
tomwalters@397
|
169 return NULL;
|
tomwalters@397
|
170 }
|
tomwalters@397
|
171
|
tomwalters@397
|
172 void GraphicsOutputDevicePlotutils::CloseFile() {
|
tomwalters@398
|
173 // Plotting library
|
tomwalters@398
|
174 if (m_iPlotHandle>0) {
|
tomwalters@398
|
175 pl_closepl();
|
tomwalters@397
|
176
|
tomwalters@398
|
177 pl_selectpl(0);
|
tomwalters@398
|
178 pl_deletepl(m_iPlotHandle);
|
tomwalters@398
|
179 m_iPlotHandle = 0;
|
tomwalters@398
|
180 }
|
tomwalters@397
|
181
|
tomwalters@398
|
182 // And the output file
|
tomwalters@398
|
183 if (m_pOutputFile) {
|
tomwalters@398
|
184 fclose(m_pOutputFile);
|
tomwalters@398
|
185 m_pOutputFile = NULL;
|
tomwalters@398
|
186 }
|
tomwalters@397
|
187 }
|
tomwalters@397
|
188
|
tomwalters@397
|
189 GraphicsOutputDevicePlotutils::~GraphicsOutputDevicePlotutils() {
|
tomwalters@398
|
190 // Output file should be closed by gRelease()
|
tomwalters@398
|
191 AIM_ASSERT(!m_pOutputFile);
|
tomwalters@398
|
192 AIM_ASSERT(!m_iPlotHandle);
|
tomwalters@398
|
193 CloseFile();
|
tomwalters@397
|
194 }
|
tomwalters@397
|
195
|
tomwalters@397
|
196 PixelFormat GraphicsOutputDevicePlotutils::GetPixelFormat() {
|
tomwalters@397
|
197 return AIM_PIX_FMT_RGB24_24;
|
tomwalters@397
|
198 }
|
tomwalters@397
|
199
|
tomwalters@397
|
200 void GraphicsOutputDevicePlotutils::gGrab() {
|
tomwalters@398
|
201 // Open file
|
tomwalters@398
|
202 if (!OpenFile(m_iFileNumber)) {
|
tomwalters@398
|
203 return;
|
tomwalters@397
|
204 }
|
tomwalters@398
|
205 // Setup plotting area
|
tomwalters@398
|
206 pl_fspace(0.0, 0.0, 1.0, 1.0);
|
tomwalters@398
|
207 pl_flinewidth(0.0001);
|
tomwalters@398
|
208 pl_pencolorname("darkblue");
|
tomwalters@398
|
209 pl_erase();
|
tomwalters@397
|
210 }
|
tomwalters@397
|
211
|
tomwalters@397
|
212 void GraphicsOutputDevicePlotutils::gBeginLineStrip() {
|
tomwalters@398
|
213 m_bIsFirstVertex = true;
|
tomwalters@398
|
214 m_iVertexType = VertexTypeLine;
|
tomwalters@398
|
215 pl_filltype(0);
|
tomwalters@397
|
216 }
|
tomwalters@397
|
217
|
tomwalters@397
|
218 void GraphicsOutputDevicePlotutils::gBeginQuadStrip() {
|
tomwalters@398
|
219 m_bIsFirstVertex = true;
|
tomwalters@398
|
220 m_iVertexType = VertexTypeQuad;
|
tomwalters@398
|
221 m_iPrevVertexCount = 0;
|
tomwalters@398
|
222 pl_filltype(1);
|
tomwalters@397
|
223 }
|
tomwalters@397
|
224
|
tomwalters@397
|
225 void GraphicsOutputDevicePlotutils::gColor3f(float r, float g, float b) {
|
tomwalters@398
|
226 if (m_bInvertColors) {
|
tomwalters@398
|
227 r = 1-r;
|
tomwalters@398
|
228 g = 1-g;
|
tomwalters@398
|
229 b = 1-b;
|
tomwalters@398
|
230 }
|
tomwalters@398
|
231 int ir = (int)(r*0xffff);
|
tomwalters@398
|
232 int ig = (int)(g*0xffff);
|
tomwalters@398
|
233 int ib = (int)(b*0xffff);
|
tomwalters@398
|
234 ir = MIN(0xffff, MAX(0,ir));
|
tomwalters@398
|
235 ig = MIN(0xffff, MAX(0,ig));
|
tomwalters@398
|
236 ib = MIN(0xffff, MAX(0,ib));
|
tomwalters@398
|
237 pl_color(ir, ig, ib);
|
tomwalters@397
|
238 }
|
tomwalters@397
|
239
|
tomwalters@397
|
240 void GraphicsOutputDevicePlotutils::gVertex3f(float x, float y, float z) {
|
tomwalters@398
|
241 switch(m_iVertexType) {
|
tomwalters@398
|
242 case VertexTypeLine:
|
tomwalters@398
|
243 if (m_bIsFirstVertex) {
|
tomwalters@398
|
244 m_bIsFirstVertex = false;
|
tomwalters@398
|
245 pl_fmove(x, y);
|
tomwalters@398
|
246 } else {
|
tomwalters@398
|
247 pl_fcont(x, y);
|
tomwalters@398
|
248 }
|
tomwalters@398
|
249 break;
|
tomwalters@398
|
250 case VertexTypeQuad:
|
tomwalters@398
|
251 /* Store vertices until we got four in a row.
|
tomwalters@398
|
252 * The order of vertices when processing quads is:
|
tomwalters@398
|
253 * 1-----3-----5
|
tomwalters@398
|
254 * | | |
|
tomwalters@398
|
255 * 0-----2-----4
|
tomwalters@398
|
256 */
|
tomwalters@398
|
257 if (m_iPrevVertexCount>=3) {
|
tomwalters@398
|
258 // Plot this quad
|
tomwalters@398
|
259 pl_fmove(m_aPrevX[0],m_aPrevY[0]);
|
tomwalters@398
|
260 pl_fcont(m_aPrevX[1],m_aPrevY[1]);
|
tomwalters@398
|
261 pl_fcont(x,y);
|
tomwalters@398
|
262 pl_fcont(m_aPrevX[2],m_aPrevY[2]);
|
tomwalters@398
|
263 pl_endpath();
|
tomwalters@398
|
264 // Last vertices of this quad are the first of the next
|
tomwalters@398
|
265 m_aPrevX[0] = m_aPrevX[2];
|
tomwalters@398
|
266 m_aPrevY[0] = m_aPrevY[2];
|
tomwalters@398
|
267 m_aPrevX[1] = x;
|
tomwalters@398
|
268 m_aPrevY[1] = y;
|
tomwalters@398
|
269 m_iPrevVertexCount = 2;
|
tomwalters@398
|
270 } else {
|
tomwalters@398
|
271 // Not at the fourth, keep storing
|
tomwalters@398
|
272 m_aPrevX[m_iPrevVertexCount] = x;
|
tomwalters@398
|
273 m_aPrevY[m_iPrevVertexCount] = y;
|
tomwalters@398
|
274 m_iPrevVertexCount++;
|
tomwalters@398
|
275 }
|
tomwalters@398
|
276 break;
|
tomwalters@398
|
277 default:
|
tomwalters@398
|
278 // Should not happen
|
tomwalters@398
|
279 AIM_ASSERT(0);
|
tomwalters@398
|
280 }
|
tomwalters@397
|
281 }
|
tomwalters@397
|
282
|
tomwalters@397
|
283 void GraphicsOutputDevicePlotutils::gEnd() {
|
tomwalters@398
|
284 pl_endpath();
|
tomwalters@398
|
285 m_iVertexType = VertexTypeNone;
|
tomwalters@397
|
286 }
|
tomwalters@397
|
287
|
tomwalters@397
|
288 void GraphicsOutputDevicePlotutils::gText3f(float x,
|
tomwalters@397
|
289 float y,
|
tomwalters@397
|
290 float z,
|
tomwalters@397
|
291 const char *sStr,
|
tomwalters@397
|
292 bool bRotated) {
|
tomwalters@398
|
293 if (bRotated) {
|
tomwalters@398
|
294 pl_textangle(90);
|
tomwalters@398
|
295 pl_fmove(x, y);
|
tomwalters@398
|
296 pl_alabel('l', 't', sStr);
|
tomwalters@398
|
297 } else {
|
tomwalters@398
|
298 pl_textangle(0);
|
tomwalters@398
|
299 pl_fmove(x, y);
|
tomwalters@398
|
300 pl_alabel('l', 'b', sStr);
|
tomwalters@398
|
301 }
|
tomwalters@397
|
302 }
|
tomwalters@397
|
303
|
tomwalters@397
|
304 void GraphicsOutputDevicePlotutils::gRelease() {
|
tomwalters@398
|
305 AIM_ASSERT(m_pOutputFile);
|
tomwalters@398
|
306 AIM_ASSERT(m_iPlotHandle>0);
|
tomwalters@398
|
307 CloseFile();
|
tomwalters@398
|
308 m_iFileNumber++;
|
tomwalters@397
|
309 }
|