tomwalters@397: // Copyright 2006, Willem van Engen tomwalters@397: // tomwalters@397: // AIM-C: A C++ implementation of the Auditory Image Model tomwalters@397: // http://www.acousticscale.org/AIMC tomwalters@397: // tomwalters@397: // Licensed under the Apache License, Version 2.0 (the "License"); tomwalters@397: // you may not use this file except in compliance with the License. tomwalters@397: // You may obtain a copy of the License at tomwalters@397: // tomwalters@397: // http://www.apache.org/licenses/LICENSE-2.0 tomwalters@397: // tomwalters@397: // Unless required by applicable law or agreed to in writing, software tomwalters@397: // distributed under the License is distributed on an "AS IS" BASIS, tomwalters@397: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. tomwalters@397: // See the License for the specific language governing permissions and tomwalters@397: // limitations under the License. tomwalters@397: tomwalters@397: /*! tomwalters@397: * \file tomwalters@397: * \brief Output device for output to a graphics file using plotutils tomwalters@397: * tomwalters@397: * \author Willem van Engen tomwalters@397: * \date created 2006/10/13 tomwalters@397: * \version \$Id: GraphicsOutputDevicePlotutils.cpp 493 2007-11-27 10:59:20Z tom $ tomwalters@397: */ tomwalters@397: #include "Support/Common.h" tomwalters@397: tomwalters@397: #include tomwalters@397: #include tomwalters@397: #include tomwalters@397: #include tomwalters@397: #include tomwalters@397: tomwalters@397: #include "Support/util.h" tomwalters@397: #include "Modules/Output/Graphics/Devices/GraphicsOutputDevicePlotutils.h" tomwalters@397: tomwalters@397: GraphicsOutputDevicePlotutils::GraphicsOutputDevicePlotutils(Parameters *pParam) tomwalters@397: : GraphicsOutputDevice(pParam) { tomwalters@398: m_iPlotHandle = 0; tomwalters@398: m_pOutputFile = NULL; tomwalters@398: m_iFileNumber = 0; tomwalters@398: m_iVertexType = VertexTypeNone; tomwalters@398: m_bUseMemoryBuffer = false; tomwalters@398: m_pMemoryBuffer = NULL; tomwalters@398: m_uWidth=0; tomwalters@398: m_uHeight=0; tomwalters@397: } tomwalters@397: tomwalters@397: bool GraphicsOutputDevicePlotutils::Initialize(const char *sDir) { tomwalters@397: Init(); tomwalters@397: tomwalters@398: //! \todo Output to file if sDir is a file, to directory with multiple tomwalters@397: //! images if it's a directory. tomwalters@398: strncpy(m_sDir, sDir, sizeof(m_sDir)/sizeof(m_sDir[0])); tomwalters@397: tomwalters@398: /* Try to open an image to see if everything is allright. We want to avoid tomwalters@398: * errors in the main Process()ing loop. */ tomwalters@398: if (!OpenFile(0)) { tomwalters@398: //! \todo Better error message that is more specific about the cause. tomwalters@398: AIM_ERROR(_T("Could not open output directory '%s' using graphics format '%s'."), tomwalters@398: m_sDir, m_pParam->GetString("output.img.format") ); tomwalters@398: return false; tomwalters@398: } tomwalters@398: CloseFile(); tomwalters@398: return true; tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::Init() { tomwalters@397: AIM_ASSERT(m_pParam); tomwalters@398: /* tomwalters@398: * Set parameters tomwalters@398: */ tomwalters@398: pl_parampl("BG_COLOR", (void*)m_pParam->GetString("output.img.color.background")); tomwalters@398: // Handle GIFs as other output formats, don't merge frames into single GIF. tomwalters@398: pl_parampl("GIF_ANIMATION", (void*)"no"); tomwalters@398: pl_parampl("INTERLACE", (void*)"no"); tomwalters@397: tomwalters@398: m_bInvertColors = m_pParam->GetBool("output.img.color.invert"); tomwalters@397: tomwalters@398: // Output size! tomwalters@398: m_uWidth = m_pParam->GetUInt("output.img.width"); tomwalters@398: m_uHeight = m_pParam->GetUInt("output.img.height"); tomwalters@398: char strSize[100]; tomwalters@398: snprintf(strSize, sizeof(strSize)/sizeof(strSize[0]), "%ux%u", m_uWidth, m_uHeight); tomwalters@398: pl_parampl("BITMAPSIZE", (void*)strSize); tomwalters@397: } tomwalters@397: tomwalters@397: bool GraphicsOutputDevicePlotutils::Initialize() { tomwalters@397: Init(); tomwalters@397: m_bUseMemoryBuffer = true; tomwalters@397: return(true); tomwalters@397: } tomwalters@397: tomwalters@397: bool GraphicsOutputDevicePlotutils::OpenFile(unsigned int index) { tomwalters@397: const char *strPlottype = m_pParam->GetString("output.img.format"); tomwalters@397: if (!m_bUseMemoryBuffer) { tomwalters@397: char sFilename[PATH_MAX]; tomwalters@397: struct stat fileinfo; tomwalters@397: tomwalters@397: // Get filename without trailing slash tomwalters@397: strncpy(sFilename, m_sDir, sizeof(sFilename)/sizeof(sFilename[0])); tomwalters@397: #ifdef _WINDOWS tomwalters@397: if (sFilename[strlen(sFilename)-1]=='\\') { tomwalters@397: sFilename[strlen(sFilename)-1]='\0'; tomwalters@397: } tomwalters@397: #else tomwalters@397: if (sFilename[strlen(sFilename)-1]=='/') { tomwalters@397: sFilename[strlen(sFilename)-1]='\0'; tomwalters@397: } tomwalters@397: #endif tomwalters@397: // Enumerate files it m_sDir is a directory. tomwalters@397: if ( stat(sFilename, &fileinfo)==0 && (fileinfo.st_mode & S_IFDIR) ) { tomwalters@397: // We have a directory: enumerate with index tomwalters@397: snprintf(sFilename, sizeof(sFilename)/sizeof(sFilename[0]),"%s%06d.%s", m_sDir, index, strPlottype); tomwalters@397: // If type is 'auto', fallback to 'png' tomwalters@397: if (strcmp(strPlottype, "auto")==0) tomwalters@397: strPlottype = "png"; tomwalters@397: } else { tomwalters@397: // We have a (probabely non-existant) file. Auto-detect type by extension if requested tomwalters@397: strncpy(sFilename, m_sDir, sizeof(sFilename)/sizeof(sFilename[0])); tomwalters@397: char *pDot = strrchr(sFilename, '.'); tomwalters@397: if (!pDot) { tomwalters@397: AIM_ERROR(_T("Please supply extension on filename when using 'auto' format: '%s'"), sFilename); tomwalters@397: return false; tomwalters@397: } tomwalters@397: strPlottype = &pDot[1]; tomwalters@397: } tomwalters@397: if ((m_pOutputFile = fopen(sFilename, "wb")) == NULL) { tomwalters@397: return false; tomwalters@397: } tomwalters@397: } else { tomwalters@397: #if !defined(_WINDOWS) && !defined(_MACOSX) tomwalters@397: if ((m_pOutputFile=open_memstream(&m_pMemoryBuffer, &m_sMemoryBufferSize))==NULL) tomwalters@397: #endif tomwalters@397: return false; tomwalters@397: strPlottype="pnm"; // Force pnm format or this doesn't work tomwalters@397: } tomwalters@397: tomwalters@398: /* tomwalters@398: * Create a plotter tomwalters@398: * tomwalters@398: * Plotutils knows the following types for file output: tomwalters@398: * pnm gif ai ps gif pcl hpgl tek meta tomwalters@398: */ tomwalters@398: if ((m_iPlotHandle = pl_newpl(strPlottype, tomwalters@397: NULL, tomwalters@397: m_pOutputFile, tomwalters@397: stderr)) < 0 ) { tomwalters@398: return false; tomwalters@398: } tomwalters@398: pl_selectpl(m_iPlotHandle); tomwalters@397: tomwalters@398: if ( pl_openpl() < 0) { tomwalters@398: return false; tomwalters@398: } tomwalters@397: tomwalters@398: // Now setup things for this plotter tomwalters@398: pl_fontname(m_pParam->GetString("output.img.fontname")); tomwalters@398: //! \todo Make fontsize work in Plotutils, currently disabled tomwalters@398: //pl_ffontsize(m_pParam->GetUInt("output.fontsize")); tomwalters@397: tomwalters@398: return true; tomwalters@397: } tomwalters@397: tomwalters@397: char* GraphicsOutputDevicePlotutils::GetBuffer() { tomwalters@397: if(m_bUseMemoryBuffer && (m_pMemoryBuffer!=NULL)) tomwalters@397: return (&m_pMemoryBuffer[m_sMemoryBufferSize-(m_uWidth*m_uHeight*3)]); tomwalters@397: else tomwalters@397: return NULL; tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::CloseFile() { tomwalters@398: // Plotting library tomwalters@398: if (m_iPlotHandle>0) { tomwalters@398: pl_closepl(); tomwalters@397: tomwalters@398: pl_selectpl(0); tomwalters@398: pl_deletepl(m_iPlotHandle); tomwalters@398: m_iPlotHandle = 0; tomwalters@398: } tomwalters@397: tomwalters@398: // And the output file tomwalters@398: if (m_pOutputFile) { tomwalters@398: fclose(m_pOutputFile); tomwalters@398: m_pOutputFile = NULL; tomwalters@398: } tomwalters@397: } tomwalters@397: tomwalters@397: GraphicsOutputDevicePlotutils::~GraphicsOutputDevicePlotutils() { tomwalters@398: // Output file should be closed by gRelease() tomwalters@398: AIM_ASSERT(!m_pOutputFile); tomwalters@398: AIM_ASSERT(!m_iPlotHandle); tomwalters@398: CloseFile(); tomwalters@397: } tomwalters@397: tomwalters@397: PixelFormat GraphicsOutputDevicePlotutils::GetPixelFormat() { tomwalters@397: return AIM_PIX_FMT_RGB24_24; tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::gGrab() { tomwalters@398: // Open file tomwalters@398: if (!OpenFile(m_iFileNumber)) { tomwalters@398: return; tomwalters@397: } tomwalters@398: // Setup plotting area tomwalters@398: pl_fspace(0.0, 0.0, 1.0, 1.0); tomwalters@398: pl_flinewidth(0.0001); tomwalters@398: pl_pencolorname("darkblue"); tomwalters@398: pl_erase(); tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::gBeginLineStrip() { tomwalters@398: m_bIsFirstVertex = true; tomwalters@398: m_iVertexType = VertexTypeLine; tomwalters@398: pl_filltype(0); tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::gBeginQuadStrip() { tomwalters@398: m_bIsFirstVertex = true; tomwalters@398: m_iVertexType = VertexTypeQuad; tomwalters@398: m_iPrevVertexCount = 0; tomwalters@398: pl_filltype(1); tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::gColor3f(float r, float g, float b) { tomwalters@398: if (m_bInvertColors) { tomwalters@398: r = 1-r; tomwalters@398: g = 1-g; tomwalters@398: b = 1-b; tomwalters@398: } tomwalters@398: int ir = (int)(r*0xffff); tomwalters@398: int ig = (int)(g*0xffff); tomwalters@398: int ib = (int)(b*0xffff); tomwalters@398: ir = MIN(0xffff, MAX(0,ir)); tomwalters@398: ig = MIN(0xffff, MAX(0,ig)); tomwalters@398: ib = MIN(0xffff, MAX(0,ib)); tomwalters@398: pl_color(ir, ig, ib); tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::gVertex3f(float x, float y, float z) { tomwalters@398: switch(m_iVertexType) { tomwalters@398: case VertexTypeLine: tomwalters@398: if (m_bIsFirstVertex) { tomwalters@398: m_bIsFirstVertex = false; tomwalters@398: pl_fmove(x, y); tomwalters@398: } else { tomwalters@398: pl_fcont(x, y); tomwalters@398: } tomwalters@398: break; tomwalters@398: case VertexTypeQuad: tomwalters@398: /* Store vertices until we got four in a row. tomwalters@398: * The order of vertices when processing quads is: tomwalters@398: * 1-----3-----5 tomwalters@398: * | | | tomwalters@398: * 0-----2-----4 tomwalters@398: */ tomwalters@398: if (m_iPrevVertexCount>=3) { tomwalters@398: // Plot this quad tomwalters@398: pl_fmove(m_aPrevX[0],m_aPrevY[0]); tomwalters@398: pl_fcont(m_aPrevX[1],m_aPrevY[1]); tomwalters@398: pl_fcont(x,y); tomwalters@398: pl_fcont(m_aPrevX[2],m_aPrevY[2]); tomwalters@398: pl_endpath(); tomwalters@398: // Last vertices of this quad are the first of the next tomwalters@398: m_aPrevX[0] = m_aPrevX[2]; tomwalters@398: m_aPrevY[0] = m_aPrevY[2]; tomwalters@398: m_aPrevX[1] = x; tomwalters@398: m_aPrevY[1] = y; tomwalters@398: m_iPrevVertexCount = 2; tomwalters@398: } else { tomwalters@398: // Not at the fourth, keep storing tomwalters@398: m_aPrevX[m_iPrevVertexCount] = x; tomwalters@398: m_aPrevY[m_iPrevVertexCount] = y; tomwalters@398: m_iPrevVertexCount++; tomwalters@398: } tomwalters@398: break; tomwalters@398: default: tomwalters@398: // Should not happen tomwalters@398: AIM_ASSERT(0); tomwalters@398: } tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::gEnd() { tomwalters@398: pl_endpath(); tomwalters@398: m_iVertexType = VertexTypeNone; tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::gText3f(float x, tomwalters@397: float y, tomwalters@397: float z, tomwalters@397: const char *sStr, tomwalters@397: bool bRotated) { tomwalters@398: if (bRotated) { tomwalters@398: pl_textangle(90); tomwalters@398: pl_fmove(x, y); tomwalters@398: pl_alabel('l', 't', sStr); tomwalters@398: } else { tomwalters@398: pl_textangle(0); tomwalters@398: pl_fmove(x, y); tomwalters@398: pl_alabel('l', 'b', sStr); tomwalters@398: } tomwalters@397: } tomwalters@397: tomwalters@397: void GraphicsOutputDevicePlotutils::gRelease() { tomwalters@398: AIM_ASSERT(m_pOutputFile); tomwalters@398: AIM_ASSERT(m_iPlotHandle>0); tomwalters@398: CloseFile(); tomwalters@398: m_iFileNumber++; tomwalters@397: }