X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=blobdiff_plain;f=include%2Fimagefile.h;h=3587f1cde01e5cc90b905ea5bafd9874200ca4d5;hp=7c6c84a93782d6aea4f2f96a24d30c3f901ba808;hb=9b2bb510160bdb56f04847f5b55ab61dd8a47976;hpb=08f34bf3ba14d4f436f4d2ef0ee5af1d6eb266ac diff --git a/include/imagefile.h b/include/imagefile.h index 7c6c84a..3587f1c 100644 --- a/include/imagefile.h +++ b/include/imagefile.h @@ -1,676 +1,66 @@ -#ifndef IDF_H -#define IDF_H - +/***************************************************************************** +** FILE IDENTIFICATION +** +** Name: imagefile.h +** Purpose: imagefile class header +** Programmer: Kevin Rosenberg +** Date Started: June 2000 +** +** This is part of the CTSim program +** Copyright (C) 1983-2000 Kevin Rosenberg +** +** $Id: imagefile.h,v 1.27 2001/01/02 05:34:57 kevin Exp $ +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License (version 2) as +** published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +******************************************************************************/ + +#ifndef IMAGEFILE_H +#define IMAGEFILE_H + +#ifndef MSVC +#include +#endif #include #include -#include #include #include #include "ctsupport.h" #include "fnetorderstream.h" -#include "array2d.h" - -using namespace std; - - -class Array2dFileLabel -{ -public: - kfloat64 m_calcTime; - kuint16 m_labelType; - kuint16 m_year; - kuint16 m_month; - kuint16 m_day; - kuint16 m_hour; - kuint16 m_minute; - kuint16 m_second; - string m_strLabel; - mutable string m_strDate; - - static const int L_EMPTY = 0; - static const int L_HISTORY = 1; - static const int L_USER = 2; - - Array2dFileLabel(); - - Array2dFileLabel(const char* const str, double ctime = 0.); - - Array2dFileLabel(const int type, const char* const str, double ctime = 0.); - - ~Array2dFileLabel(); - - const string& getLabelString (void) const - { return m_strLabel; } - - kfloat64 getCalcTime (void) const - { return m_calcTime; } - - kfloat64 getLabelType (void) const - { return m_labelType; } - - string& setLabelString (const char* const str) - { m_strLabel = str; return (m_strLabel); } - - string& setLabelString (const string& str) - { m_strLabel = str; return (m_strLabel); } - - const string& getDateString () const; - -private: - void init (void); - Array2dFileLabel (const Array2dFileLabel&); - Array2dFileLabel& operator= (const Array2dFileLabel&); -}; - - -template -class Array2dFile -{ -private: - void init (void); - - bool headerWrite (void); - - bool headerRead (void); - - bool arrayDataRead (void); - - bool labelSeek (unsigned int label_num); - - Array2dFile (const Array2dFile& rhs); // copy constructor - Array2dFile& operator= (const Array2dFile&); // assignment operator - - protected: - kuint16 signature; - kuint16 num_labels; - kuint16 headersize; - string filename; - int file_id; - frnetorderstream *m_pFS; - bool bHeaderWritten; - bool bDataWritten; - - kuint16 mPixelSize; - kuint16 axis_increment_known; - kfloat64 mIncX, mIncY; - kuint16 axis_extent_known; - kfloat64 mMinX, mMaxX, mMinY, mMaxY; - kfloat64 mOffsetPV, mScalePV; - kuint16 mPixelType; - kuint32 mNX; - kuint32 mNY; - - -public: - - Array2d array; - - static const int INT8 = 1; - static const int UINT8 = 2; - static const int INT16 = 3; - static const int UINT16 = 4; - static const int INT32 = 5; - static const int UINT32 = 6; - static const int FLOAT32 = 7; - static const int FLOAT64 = 8; - - Array2dFile (unsigned int nx, unsigned int ny); - Array2dFile (const char* const filename); - Array2dFile (const char* const filename, unsigned int nx, unsigned int ny); - ~Array2dFile (); - - unsigned int getNumLabels (void) const - { return num_labels; } - - bool labelRead (Array2dFileLabel& label, unsigned int label_num); - - void labelAdd (const Array2dFileLabel& label); - - void labelAdd (const char* const m_strLabel, double calc_time=0.); - - void labelAdd (int type, const char* const m_strLabel, double calc_time=0.); - - void labelsCopy (Array2dFile& file, const char* const idStr = NULL); - - void fileClose (void); - - void setPixelType (int type) - { mPixelType = type; } - - kuint32 nx (void) const - { return mNX; } - - kuint32 ny (void) const - { return mNY; } - - void setAxisIncrement (double mIncX, double mIncY); - - void setAxisExtent (double mMinX, double mMaxX, double mMinY, double mMaxY); - - void getPixelValueRange (T& pvmin, T& pvmax) const; - - void doPixelOffsetScale (double offset, double scale); - - void printLabels (ostream& os); - - T** getArray (void) const - { return (array.getArray()); } - - bool arrayDataWrite (void); - - void arrayDataClear (void); - - bool fileRead (void); - - bool fileCreate (void); - - const string& GetFilename (void) const - { return filename; } -}; - - -template -Array2dFile::Array2dFile (unsigned int x, unsigned int y) -{ - init(); - mNX = x; - mNY = y; - array.initSetSize(mNX, mNY); -} - -template -Array2dFile::Array2dFile (const char * const str, unsigned int x, unsigned int y) - : filename(str) -{ - init(); - mNX = x; - mNY = y; - array.initSetSize(mNX, mNY); -} - -template -Array2dFile::Array2dFile (const char * const str) - : filename(str) -{ - init(); -} - -template -void -Array2dFile::init (void) -{ - mPixelSize = sizeof(T); - signature = ('I' * 256 + 'F'); - mNX = 0; - mNY = 0; - headersize = 0; - num_labels = 0; - axis_increment_known = false; - axis_extent_known = false; - mIncX = mMinY = 0; - mMinX = mMaxX = mMinY = mMaxY = 0; - mOffsetPV = 0; - mScalePV = 1; - m_pFS = NULL; - -#if 0 - const type_info& t_id = typeid(T); - cout << t_id.name() << endl; - const type_info& comp_id = typeid(T); - - if (t_id == comp_id) - mPixelType = FLOAT64; - else if (t_id == typeid(kfloat32)) - mPixelType = FLOAT32; - else if (t_id == typeid(kint32)) - mPixelType = INT32; - else if (t_id == typeid(kuint32)) - mPixelType = UINT32; - else if (t_id == typeid(kint16)) - mPixelType = INT16; - else if (t_id == typeid(kuint16)) - mPixelType = UINT16; - else if (t_id == typeid(kint8)) - mPixelType = INT8; - else if (t_id == typeid(kuint8)) - mPixelType = UINT8; - else -#endif - mPixelType = 0; - - bHeaderWritten = false; - bDataWritten = false; -} - -template -Array2dFile::~Array2dFile (void) -{ - fileClose (); -} - - -template -void -Array2dFile::fileClose (void) -{ - if (m_pFS) { - headerWrite (); - m_pFS->close (); - m_pFS = NULL; - } -} - -template -bool -Array2dFile::fileCreate (void) -{ - m_pFS = new frnetorderstream (filename.c_str(), ios::out | ios::in | ios::trunc | ios::binary); - if (! m_pFS) { - sys_error (ERR_WARNING, "Error opening file %s for writing [fileCreate]", filename.c_str()); - return (false); - } - headerWrite(); - return (true); -} - -template -bool -Array2dFile::fileRead (void) -{ - m_pFS = new frnetorderstream (filename.c_str(), ios::out | ios::in | ios::binary | ios::nocreate); - if (m_pFS->fail()) { - sys_error (ERR_WARNING, "Unable to open file %s [fileRead]", filename.c_str()); - return (false); - } - - if (! headerRead()) - return false; - - array.initSetSize(mNX, mNY); - - arrayDataRead(); - - return (true); -} - -template -void -Array2dFile::setAxisIncrement (double incX, double incY) -{ - axis_increment_known = true; - mIncX = incX; - mIncY = incY; -} - -template -void -Array2dFile::setAxisExtent (double minX, double maxX, double minY, double maxY) -{ - axis_extent_known = true; - mMinX = minX; - mMaxY = maxX; - mMinX = minX; - mMaxY = maxY; -} - -template -void -Array2dFile::getPixelValueRange (T& pvmin, T& pvmax) const -{ - T** da = array.getArray(); - if (da) { - pvmax = pvmin = da[0][0]; - for (int ix = 0; ix < mNX; ix++) - for (int iy = 0; iy < mNY; iy++) - if (pvmax < da[ix][iy]) - pvmax = da[ix][iy]; - else if (pvmin > da[ix][iy]) - pvmin = da[ix][iy]; - } -} - -template -void -Array2dFile::doPixelOffsetScale (double offset, double scale) -{ - T** ad = array.getArray(); - if (ad) { - mOffsetPV = offset; - mScalePV = scale; - - for (unsigned int ix = 0; ix < mNX; ix++) - for (unsigned int iy = 0; iy < mNY; iy++) - ad[ix][iy] = (ad[ix][iy] - offset) * scale; - } -} - -template -bool -Array2dFile::headerRead (void) -{ - if (! m_pFS) { - sys_error (ERR_WARNING, "Tried to read header with file closed [headerRead]"); - return (false); - } - - m_pFS->seekg (0); - kuint16 file_signature; - kuint16 file_mPixelSize; - kuint16 file_mPixelType; - - m_pFS->readInt16 (headersize); - m_pFS->readInt16 (file_signature); - m_pFS->readInt16 (num_labels); - m_pFS->readInt16 (file_mPixelType); - m_pFS->readInt16 (file_mPixelSize); - m_pFS->readInt32 (mNX); - m_pFS->readInt32 (mNY); - m_pFS->readInt16 (axis_increment_known); - m_pFS->readFloat64 (mIncX); - m_pFS->readFloat64 (mIncY); - m_pFS->readInt16 (axis_extent_known); - m_pFS->readFloat64 (mMinX); - m_pFS->readFloat64 (mMaxX); - m_pFS->readFloat64 (mMinY); - m_pFS->readFloat64 (mMaxY); - m_pFS->readFloat64 (mOffsetPV); - m_pFS->readFloat64 (mScalePV); - - int read_headersize = m_pFS->tellg(); - if (read_headersize != headersize) { - sys_error (ERR_WARNING, "Read headersize %d != file headersize %d", read_headersize, headersize); - return (false); - } - if (file_signature != signature) { - sys_error (ERR_WARNING, "File signature %d != true signature %d", file_signature, signature); - return (false); - } - if (file_mPixelType != mPixelType) { - sys_error (ERR_WARNING, "File pixel type %d != class pixel type %d", file_mPixelType, mPixelType); - return (false); - } - if (file_mPixelSize != mPixelSize) { - sys_error (ERR_WARNING, "File pixel size %d != class pixel size %d", file_mPixelSize, mPixelSize); - return (false); - } - - return (true); -} - -template -bool -Array2dFile::headerWrite (void) -{ - if (! m_pFS) { - sys_error (ERR_WARNING, "Tried to write header with file closed"); - return (false); - } - - m_pFS->seekp (0); - m_pFS->writeInt16 (headersize); - m_pFS->writeInt16 (signature); - m_pFS->writeInt16 (num_labels); - m_pFS->writeInt16 (mPixelType); - m_pFS->writeInt16 (mPixelSize); - m_pFS->writeInt32 (mNX); - m_pFS->writeInt32 (mNY); - m_pFS->writeInt16 (axis_increment_known); - m_pFS->writeFloat64 (mIncX); - m_pFS->writeFloat64 (mIncY); - m_pFS->writeInt16 (axis_extent_known); - m_pFS->writeFloat64 (mMinX); - m_pFS->writeFloat64 (mMaxX); - m_pFS->writeFloat64 (mMinY); - m_pFS->writeFloat64 (mMaxY); - m_pFS->writeFloat64 (mOffsetPV); - m_pFS->writeFloat64 (mScalePV); - - headersize = m_pFS->tellp(); - m_pFS->writeInt16 (headersize); - - return (true); -} - -template -bool -Array2dFile::arrayDataWrite (void) -{ - if (! m_pFS) { - sys_error (ERR_WARNING, "Tried to arrayDataWrite with !m_pFS"); - return (false); - } - - T** da = array.getArray(); - if (! da) - return (false); - - m_pFS->seekp (headersize); - for (unsigned int ix = 0; ix < mNX; ix++) { - if (NativeBigEndian()) { - for (unsigned int iy = 0; iy < mNY; iy++) { - T value = da[ix][iy]; - ConvertReverseNetworkOrder (&value, sizeof(T)); - m_pFS->write (&value, mPixelSize); - } - } else - m_pFS->write (da[ix], sizeof(T) * mNY); - } - - return (true); -} - -template -bool -Array2dFile::arrayDataRead (void) -{ - if (! m_pFS) { - sys_error (ERR_WARNING, "Tried to arrayDataRead with !m_pFS"); - return (false); - } - - T** da = array.getArray(); - if (! da) - return (false); - - m_pFS->seekg (headersize); - T pixelBuffer; - for (int ix = 0; ix < mNX; ix++) { - if (NativeBigEndian()) { - for (unsigned int iy = 0; iy < mNY; iy++) { - m_pFS->read (&pixelBuffer, mPixelSize); - ConvertReverseNetworkOrder (&pixelBuffer, sizeof(T)); - da[ix][iy] = pixelBuffer; - } - } else - m_pFS->read (da[ix], sizeof(T) * mNY); - } - - - return (true); -} - -template -bool -Array2dFile::labelSeek (unsigned int label_num) -{ - if (label_num > num_labels) { - sys_error (ERR_WARNING, "label_num %d > num_labels %d [labelSeek]"); - return (false); - } - - if (array.getArray() == NULL) { // Could not have written data if array not allocated - sys_error (ERR_WARNING, "array == NULL [labelSeek]"); - return (false); - } - - off_t pos = headersize + array.sizeofArray(); - m_pFS->seekg (pos); - - for (int i = 0; i < label_num; i++) - { - pos += 22; // Skip to string length - m_pFS->seekg (pos); - - kuint16 strlength; - m_pFS->readInt16 (strlength); - pos += 2 + strlength; // Skip label string length + data - m_pFS->seekg (pos); - } - - if (! m_pFS) - return false; - - return (true); -} - -template -bool -Array2dFile::labelRead (Array2dFileLabel& label, unsigned int label_num) -{ - if (label_num >= num_labels) { - sys_error (ERR_WARNING, "Trying to read past number of labels [labelRead]"); - return (false); - } - - if (! labelSeek (label_num)) { - sys_error (ERR_WARNING, "Error calling labelSeek"); - return (false); - } - - m_pFS->readInt16 (label.m_labelType); - m_pFS->readInt16 (label.m_year); - m_pFS->readInt16 (label.m_month); - m_pFS->readInt16 (label.m_day); - m_pFS->readInt16 (label.m_hour); - m_pFS->readInt16 (label.m_minute); - m_pFS->readInt16 (label.m_second); - m_pFS->readFloat64 (label.m_calcTime); - - kuint16 strlength; - m_pFS->readInt16 (strlength); - char str [strlength+1]; - m_pFS->read (str, strlength); - str[strlength] = 0; - label.m_strLabel = str; - - return (true); -} - - -template -void -Array2dFile::labelAdd (const char* const lstr, double calc_time=0.) -{ - labelAdd (Array2dFileLabel::L_HISTORY, lstr, calc_time); -} - -template -void -Array2dFile::labelAdd (int type, const char* const lstr, double calc_time=0.) -{ - Array2dFileLabel label (type, lstr, calc_time); - - labelAdd (label); -} - -template -void -Array2dFile::labelAdd (const Array2dFileLabel& label) -{ - labelSeek (num_labels); - - m_pFS->writeInt16 (label.m_labelType); - m_pFS->writeInt16 (label.m_year); - m_pFS->writeInt16 (label.m_month); - m_pFS->writeInt16 (label.m_day); - m_pFS->writeInt16 (label.m_hour); - m_pFS->writeInt16 (label.m_minute); - m_pFS->writeInt16 (label.m_second); - m_pFS->writeFloat64 (label.m_calcTime); - kuint16 strlength = label.m_strLabel.length(); - m_pFS->writeInt16 (strlength); - m_pFS->write (label.m_strLabel.c_str(), strlength); - - num_labels++; - - headerWrite(); -} - -template -void -Array2dFile::labelsCopy (Array2dFile& copyFile, const char* const idStr) -{ - string id = idStr; - for (int i = 0; i < copyFile.getNumLabels(); i++) { - Array2dFileLabel l; - copyFile.labelRead (l, i); - string lstr = l.getLabelString(); - lstr = idStr + lstr; - l.setLabelString (lstr); - labelAdd (l); - } -} - -template -void -Array2dFile::arrayDataClear (void) -{ - T** v = array.getArray(); - if (v) { - for (unsigned int ix = 0; ix < mNX; ix++) - for (unsigned int iy = 0; iy < mNY; iy++) - v[ix][iy] = 0; - } -} - -template -void -Array2dFile::printLabels (ostream& os) -{ - int nlabels = getNumLabels(); - - for (int i = 0; i < nlabels; i++) { - Array2dFileLabel label; - labelRead (label, i); - - if (label.getLabelType() == Array2dFileLabel::L_HISTORY) { - os << "History: " << endl; - os << " " << label.getLabelString() << endl; - os << " calc time = " << label.getCalcTime() << " secs" << endl; - os << " Timestamp = " << label.getDateString() << endl; - } else if (label.getLabelType() == Array2dFileLabel::L_USER) { - os << "Note: " << label.getLabelString() << endl; - os << " Timestamp = %s" << label.getDateString() << endl; - } - os << endl; - } -} +#include "array2dfile.h" #ifdef HAVE_MPI #include #endif -class F32Image : public Array2dFile +class F32Image : public Array2dFile { public: - F32Image (const char* const fname, unsigned int nx, unsigned int ny) - : Array2dFile::Array2dFile (fname, nx, ny) - { - setPixelType (FLOAT32); - } - - F32Image (unsigned int nx, unsigned int ny) - : Array2dFile::Array2dFile (nx, ny) - { - setPixelType (FLOAT32); - } - - F32Image (const char* const fname) - : Array2dFile::Array2dFile (fname) - { - setPixelType (FLOAT32); - } - + F32Image (int nx, int ny, int dataType = Array2dFile::DATA_TYPE_REAL); + F32Image (void); + + kfloat32** getArray (void) + { return (kfloat32**) (m_arrayData); } + + kfloat32** const getArray (void) const + { return (kfloat32** const) (m_arrayData); } + + kfloat32** getImaginaryArray (void) + { return (kfloat32**) (m_imaginaryArrayData); } + + kfloat32** const getImaginaryArray (void) const + { return (kfloat32** const) (m_imaginaryArrayData); } + #ifdef HAVE_MPI MPI::Datatype getMPIDataType (void) const { return MPI::FLOAT; } @@ -682,28 +72,25 @@ public: }; -class F64Image : public Array2dFile +class F64Image : public Array2dFile { public: - F64Image (const char* const fname, unsigned int nx, unsigned int ny) - : Array2dFile::Array2dFile (fname, nx, ny) - { - setPixelType (FLOAT64); - } - - F64Image (unsigned int nx, unsigned int ny) - : Array2dFile::Array2dFile (nx, ny) - { - setPixelType (FLOAT64); - } - - F64Image (const char* const fname) - : Array2dFile::Array2dFile (fname) - { - setPixelType (FLOAT64); - } - + F64Image (int nx, int ny, int dataType = Array2dFile::DATA_TYPE_REAL); + F64Image (void); + + kfloat64** getArray (void) + { return (kfloat64**) (m_arrayData); } + + kfloat64** const getArray (void) const + { return (kfloat64** const) (m_arrayData); } + + kfloat64** getImaginaryArray (void) + { return (kfloat64**) (m_imaginaryArrayData); } + + kfloat64** const getImaginaryArray (void) const + { return (kfloat64** const) (m_imaginaryArrayData); } + #ifdef HAVE_MPI MPI::Datatype getMPIDataType (void) const { return MPI::DOUBLE; } @@ -719,47 +106,98 @@ typedef F64Image ImageFileBase; typedef kfloat64 ImageFileValue; typedef kfloat64* ImageFileColumn; typedef kfloat64** ImageFileArray; +typedef kfloat64** const ImageFileArrayConst; +typedef const kfloat64* ImageFileColumnConst; #else typedef F32Image ImageFileBase; typedef kfloat32 ImageFileValue; typedef kfloat32* ImageFileColumn; typedef kfloat32** ImageFileArray; +typedef kfloat32** const ImageFileArrayConst; +typedef const kfloat32* ImageFileColumnConst; #endif class ImageFile : public ImageFileBase -{ - public: - ImageFile (const char* const fname, unsigned int nx, unsigned int ny) - : ImageFileBase (fname, nx, ny) - {} - - ImageFile (unsigned int nx, unsigned int ny) +{ +private: + + static const char* s_aszFormatName[]; + static const char* s_aszFormatTitle[]; + static const int s_iFormatCount; + +public: + + static const int FORMAT_INVALID; + static const int FORMAT_PGM; + static const int FORMAT_PGMASCII; +#if HAVE_PNG + static const int FORMAT_PNG; + static const int FORMAT_PNG16; +#endif + + static const int getFormatCount() {return s_iFormatCount;} + static const char** getFormatNameArray() {return s_aszFormatName;} + static const char** getFormatTitleArray() {return s_aszFormatTitle;} + static int convertFormatNameToID (const char* const formatName); + static const char* convertFormatIDToName (const int formatID); + static const char* convertFormatIDToTitle (const int formatID); + + ImageFile (int nx, int ny) : ImageFileBase (nx, ny) {} - ImageFile (const char* const fname) - : ImageFileBase (fname) + ImageFile (void) + : ImageFileBase () {} + + bool convertRealToComplex (); + bool convertComplexToReal (); - void filterResponse (const char* const domainName, double bw, const char* const filterName, double filt_param); - - void statistics (double& min, double& max, double& mean, double& mode, double& median, double& stddev) const; - - void printStatistics (ostream& os) const; + void filterResponse (const char* const domainName, double bw, const char* const filterName, double filt_param, double dInputScale = 1., double dOutputScale = 1.); + void statistics (double& min, double& max, double& mean, double& mode, double& median, double& stddev) const; + void statistics (ImageFileArrayConst v, double& min, double& max, double& mean, double& mode, double& median, double& stddev) const; + void getMinMax (double& min, double& max) const; + void printStatistics (std::ostream& os) const; bool comparativeStatistics (const ImageFile& imComp, double& d, double& r, double& e) const; - - bool printComparativeStatistics (const ImageFile& imComp, ostream& os) const; - - int display (void); - - int displayScaling (const int scaleFactor, ImageFileValue pmin, ImageFileValue pmax); - + bool printComparativeStatistics (const ImageFile& imComp, std::ostream& os) const; + + bool subtractImages (const ImageFile& rRHS, ImageFile& result) const; + bool addImages (const ImageFile& rRHS, ImageFile& result) const; + bool multiplyImages (const ImageFile& rRHS, ImageFile& result) const; + bool divideImages (const ImageFile& rRHS, ImageFile& result) const; + + bool scaleImage (ImageFile& result) const; + + bool invertPixelValues (ImageFile& result) const; + bool sqrt (ImageFile& result) const; + bool square (ImageFile& result) const; + bool log (ImageFile& result) const; + bool exp (ImageFile& result) const; + bool fourier (ImageFile& result) const; + bool inverseFourier (ImageFile& result) const; +#ifdef HAVE_FFTW + bool fft (ImageFile& result) const; + bool ifft (ImageFile& result) const; +#endif + bool magnitude (ImageFile& result) const; + bool phase (ImageFile& result) const; + + int display (void) const; + int displayScaling (const int scaleFactor, ImageFileValue pmin, ImageFileValue pmax) const; + + bool exportImage (const char* const pszFormat, const char* const pszFilename, int nxcell, int nycell, double densmin, double densmax); + +#if HAVE_PNG + bool writeImagePNG (const char* const outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax); +#endif +#if HAVE_GD + bool writeImageGIF (const char* const outfile, int nxcell, int nycell, double densmin, double densmax); +#endif + bool writeImagePGM (const char* const outfile, int nxcell, int nycell, double densmin, double densmax); + bool writeImagePGMASCII (const char* const outfile, int nxcell, int nycell, double densmin, double densmax); }; #endif - - -