From 9b2bb510160bdb56f04847f5b55ab61dd8a47976 Mon Sep 17 00:00:00 2001 From: "Kevin M. Rosenberg" Date: Tue, 2 Jan 2001 05:34:57 +0000 Subject: [PATCH] r328: *** empty log message *** --- ChangeLog | 30 +- NEWS | 14 + TODO | 8 +- include/Makefile.am | 2 +- include/array2dfile.h | 9 +- include/ct.h | 5 +- include/imagefile.h | 42 ++- include/procsignal.h | 10 +- libctsim/Makefile.am | 2 +- libctsim/array2dfile.cpp | 83 ++++-- libctsim/imagefile.cpp | 565 +++++++++++++++++++++++-------------- libctsim/procsignal.cpp | 205 +------------- libctsupport/mathfuncs.cpp | 7 +- libctsupport/plotfile.cpp | 68 +++-- msvc/ctsim/ctsim.plg | 85 ++---- msvc/libctsim/libctsim.dsp | 8 + src/ctsim.cpp | 368 ++++++++++++------------ src/ctsim.h | 22 +- src/dialogs.cpp | 150 +++++++++- src/dialogs.h | 41 ++- src/docs.cpp | 14 +- src/docs.h | 3 +- src/views.cpp | 318 ++++++++++++++++++--- src/views.h | 15 +- tools/phm2if.cpp | 13 +- tools/phm2pj.cpp | 18 +- 26 files changed, 1306 insertions(+), 799 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9decb06..3a553b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,16 +1,32 @@ - TODO - Read PlotFile's. - Add to ctsim export of imagefiles to standard graphic formats. +TODO + Be consistant with creation of new images + copy labels from original image to new images + +3.0alpha2 - Released 1/02/01 + + * ctsim: added generation of filter images + + * ctsim: Added 2-image math functions (mul, add, div, sub) -3.0alpha2 + * ctsim: Added export of imagefiles to graphic file formats + + * ctsim: Added support for scaling imagefiles in new sizes + + * ctsim: Added ability to save standard phantom definitions as + text files suitable for reading. + * ctsim: Add labels for image transformations and display of labels + when performing properties of images. + * processsignal.cpp: Fixed "off by one" bug in - shuffleNaturalToFourierOrder when n is even. + shuffleNaturalToFourierOrder when n is even. Moved functions to + fourier.cpp - * imagefile: Added FFTW library to imagefile processing + * imagefile.cpp: Added FFTW library to imagefile processing. Converted + image math functions to complex-valued math. - * ctsim: added generation of filter images + * phantom.cpp: Added ability to save phantom files as ASCII text. 3.0alpha1 - Released 12/29/00 diff --git a/NEWS b/NEWS index efabc37..e2fd6c6 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,17 @@ +Version 3.0alpha Features + +* Creation of arbitrary filter images + +* All features of command line tools are now in graphical ctsim program! + +* Complex-valued image files now supported, lots of image math + functions added including fourier transformations + +* Visual and statistical image comparision functions + +* 2D plots of row and column data of single and comparison images + + Version 2.5 of CTSim has been released! New Features of CTSim version 2.5: diff --git a/TODO b/TODO index 69aa217..588b906 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,6 @@ Add help button onto dialog's for reconstruction & projections. -Consider use of wxWindows help file classes. - -Consider changing POL to to read tag tokens. -Consider being able to write Phantom files as text and view as -text in ctsim. +Consider use of wxWindows help file classes. -FFT filtering requires FFTW library. Add a basic FFT routine. +FFT filtering requires FFTW library: add a basic FFT routine. diff --git a/include/Makefile.am b/include/Makefile.am index bc6c111..f583054 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,4 +1,4 @@ -noinst_HEADERS=ct.h ezplot.h pol.h sgp.h array2d.h imagefile.h backprojectors.h mpiworld.h fnetorderstream.h phantom.h timer.h sstream_subst scanner.h projections.h ctsupport.h filter.h array2dfile.h trace.h transformmatrix.h procsignal.h reconstruct.h plotfile.h hashtable.h +noinst_HEADERS=ct.h ezplot.h pol.h sgp.h array2d.h imagefile.h backprojectors.h mpiworld.h fnetorderstream.h phantom.h timer.h sstream_subst scanner.h projections.h ctsupport.h filter.h array2dfile.h trace.h transformmatrix.h procsignal.h reconstruct.h plotfile.h hashtable.h fourier.h diff --git a/include/array2dfile.h b/include/array2dfile.h index 22e8b61..e9d4ab2 100644 --- a/include/array2dfile.h +++ b/include/array2dfile.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: array2dfile.h,v 1.14 2001/01/01 10:14:34 kevin Exp $ +** $Id: array2dfile.h,v 1.15 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 @@ -89,6 +89,7 @@ public: const std::string& getDateString () const; void print (std::ostream& os) const; + void printBrief (std::ostream& os) const; Array2dFileLabel (const Array2dFileLabel& rhs); @@ -201,7 +202,11 @@ public: const std::string& getFilename (void) const { return m_filename; } - void printLabels (std::ostream& os) const; + void printLabels (std::ostream& os) const; + void printLabelsBrief (std::ostream& os) const; + + unsigned int nLabels() const + { return m_labels.size(); } typedef std::vector::iterator labelIterator; typedef std::vector::const_iterator constLabelIterator; diff --git a/include/ct.h b/include/ct.h index 652df0c..b618130 100644 --- a/include/ct.h +++ b/include/ct.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ct.h,v 1.47 2000/12/19 21:37:51 kevin Exp $ +** $Id: ct.h,v 1.48 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 @@ -170,7 +170,8 @@ extern "C" { #include "phantom.h" #include "scanner.h" #include "backprojectors.h" -#include "filter.h" +#include "filter.h" +#include "fourier.h" #include "procsignal.h" #include "projections.h" #include "reconstruct.h" diff --git a/include/imagefile.h b/include/imagefile.h index 945bdbf..3587f1c 100644 --- a/include/imagefile.h +++ b/include/imagefile.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: imagefile.h,v 1.26 2001/01/01 10:14:34 kevin Exp $ +** $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 @@ -119,8 +119,30 @@ typedef const kfloat32* ImageFileColumnConst; class ImageFile : public ImageFileBase -{ - public: +{ +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) {} @@ -132,7 +154,7 @@ class ImageFile : public ImageFileBase bool convertRealToComplex (); bool convertComplexToReal (); - void filterResponse (const char* const domainName, double bw, const char* const filterName, double filt_param); + 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; @@ -146,6 +168,8 @@ class ImageFile : public ImageFileBase 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; @@ -162,15 +186,17 @@ class ImageFile : public ImageFileBase 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 - void writeImagePNG (const char *outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax); + bool writeImagePNG (const char* const outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax); #endif #if HAVE_GD - void writeImageGIF (const char *outfile, int nxcell, int nycell, double densmin, double densmax); + bool writeImageGIF (const char* const outfile, int nxcell, int nycell, double densmin, double densmax); #endif - void writeImagePGM (const char *outfile, int nxcell, int nycell, double densmin, double densmax); - void writeImagePGMASCII (const char *outfile, int nxcell, int nycell, double densmin, double densmax); + 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); }; diff --git a/include/procsignal.h b/include/procsignal.h index 8eb98c6..2be3b7c 100644 --- a/include/procsignal.h +++ b/include/procsignal.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: procsignal.h,v 1.10 2001/01/01 10:14:34 kevin Exp $ +** $Id: procsignal.h,v 1.11 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 @@ -105,14 +105,6 @@ class ProcessSignal { static void finiteFourierTransform (const double input[], std::complex output[], const int n, const int direction); static void finiteFourierTransform (const std::complex input[], std::complex output[], const int n, const int direction); static void finiteFourierTransform (const std::complex input[], double output[], const int n, const int direction); - - - static void shuffleNaturalToFourierOrder (float* pdVector, const int n); - static void shuffleNaturalToFourierOrder (double* pdVector, const int n); - static void shuffleNaturalToFourierOrder (std::complex* pdVector, const int n); - static void shuffleFourierToNaturalOrder (float* pdVector, const int n); - static void shuffleFourierToNaturalOrder (double* pdVector, const int n); - static void shuffleFourierToNaturalOrder (std::complex* pdVector, const int n); private: diff --git a/libctsim/Makefile.am b/libctsim/Makefile.am index 28b3173..e8def37 100644 --- a/libctsim/Makefile.am +++ b/libctsim/Makefile.am @@ -1,5 +1,5 @@ noinst_LIBRARIES = libctsim.a -libctsim_a_SOURCES = filter.cpp scanner.cpp projections.cpp phantom.cpp imagefile.cpp backprojectors.cpp array2dfile.cpp trace.cpp procsignal.cpp reconstruct.cpp +libctsim_a_SOURCES = filter.cpp scanner.cpp projections.cpp phantom.cpp imagefile.cpp backprojectors.cpp array2dfile.cpp trace.cpp procsignal.cpp reconstruct.cpp fourier.cpp INCLUDES=@my_includes@ EXTRA_DIST=Makefile.nt diff --git a/libctsim/array2dfile.cpp b/libctsim/array2dfile.cpp index d0f2d68..c450a0e 100644 --- a/libctsim/array2dfile.cpp +++ b/libctsim/array2dfile.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: array2dfile.cpp,v 1.23 2001/01/01 10:14:34 kevin Exp $ +** $Id: array2dfile.cpp,v 1.24 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 @@ -137,23 +137,38 @@ Array2dFileLabel::operator= (const Array2dFileLabel& rhs) return (*this); } -void -Array2dFileLabel::print (std::ostream& os) const -{ - if (m_labelType == L_HISTORY) { - os << "History: " << std::endl; - os << " " << m_strLabel << std::endl; - os << " calc time = " << m_calcTime << " secs" << std::endl; - os << " Timestamp = " << getDateString() << std::endl; - } else if (m_labelType == L_USER) { - os << "Note: " << m_strLabel << std::endl; - os << " Timestamp = %s" << getDateString() << std::endl; - } else { - os << "Unknown (" << m_labelType << "): " << m_strLabel << std::endl; - os << " Timestamp = %s" << getDateString() << std::endl; - } -} - +void +Array2dFileLabel::print (std::ostream& os) const +{ + if (m_labelType == L_HISTORY) { + os << "History: " << std::endl; + os << " " << m_strLabel << std::endl; + os << " calc time = " << m_calcTime << " secs" << std::endl; + os << " Timestamp = " << getDateString() << std::endl; + } else if (m_labelType == L_USER) { + os << "Note: " << m_strLabel << std::endl; + os << " Timestamp = %s" << getDateString() << std::endl; + } else { + os << "Unknown (" << m_labelType << "): " << m_strLabel << std::endl; + os << " Timestamp = %s" << getDateString() << std::endl; + } +} + +void +Array2dFileLabel::printBrief (std::ostream& os) const +{ + if (m_labelType == L_HISTORY) { + os << "History ("; + if (m_calcTime > 0) + os << m_calcTime << " secs, "; + os << getDateString() << "): " << m_strLabel << std::endl; + } else if (m_labelType == L_USER) { + os << "Note (" << getDateString() << "): " << m_strLabel << std::endl; + } else { + os << "Unknown (" << getDateString() << "): " << m_strLabel << std::endl; + } +} + /////////////////////////////////////////////////////////////////////////// // CLASS IMPLEMENTATION @@ -660,17 +675,27 @@ Array2dFile::arrayDataClear (void) } } -void -Array2dFile::printLabels (std::ostream& os) const -{ - for (constLabelIterator l = m_labels.begin(); l != m_labels.end(); l++) { - const Array2dFileLabel& label = **l; - - label.print (os); - os << std::endl; - } -} - +void +Array2dFile::printLabels (std::ostream& os) const +{ + for (constLabelIterator l = m_labels.begin(); l != m_labels.end(); l++) { + const Array2dFileLabel& label = **l; + + label.print (os); + os << std::endl; + } +} + +void +Array2dFile::printLabelsBrief (std::ostream& os) const +{ + for (constLabelIterator l = m_labels.begin(); l != m_labels.end(); l++) { + const Array2dFileLabel& label = **l; + + label.printBrief (os); + } +} + const Array2dFileLabel& Array2dFile::labelGet (int i) const diff --git a/libctsim/imagefile.cpp b/libctsim/imagefile.cpp index df647ce..0cbd678 100644 --- a/libctsim/imagefile.cpp +++ b/libctsim/imagefile.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: imagefile.cpp,v 1.28 2001/01/01 10:14:34 kevin Exp $ +** $Id: imagefile.cpp,v 1.29 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 @@ -27,6 +27,35 @@ #include "ct.h" +const int ImageFile::FORMAT_INVALID = -1; +const int ImageFile::FORMAT_PGM = 0; +const int ImageFile::FORMAT_PGMASCII = 1; +#ifdef HAVE_PNG +const int ImageFile::FORMAT_PNG = 2; +const int ImageFile::FORMAT_PNG16 = 3; +#endif + +const char* ImageFile::s_aszFormatName[] = +{ + {"pgm"}, + {"pgmascii"}, +#ifdef HAVE_PNG + {"png"}, + {"png16"}, +#endif +}; + +const char* ImageFile::s_aszFormatTitle[] = +{ + {"PGM"}, + {"PGM ASCII"}, + {"PNG"}, + {"PNG 16-bit"}, +}; + +const int ImageFile::s_iFormatCount = sizeof(s_aszFormatName) / sizeof(const char*); + + F32Image::F32Image (int nx, int ny, int dataType) : Array2dFile (nx, ny, sizeof(kfloat32), Array2dFile::PIXEL_FLOAT32, dataType) @@ -55,7 +84,7 @@ F64Image::F64Image (void) } void -ImageFile::filterResponse (const char* const domainName, double bw, const char* const filterName, double filt_param) +ImageFile::filterResponse (const char* const domainName, double bw, const char* const filterName, double filt_param, double dInputScale, double dOutputScale) { ImageFileArray v = getArray(); SignalFilter filter (filterName, domainName, bw, filt_param); @@ -73,9 +102,9 @@ ImageFile::filterResponse (const char* const domainName, double bw, const char* for (int ix = 0; ix < m_nx; ix++) for (int iy = 0; iy < m_ny; iy++) { - long lD2 = (ix - iXCenter) * (ix - iXCenter) + (iy - iYCenter) * (iy - iYCenter); - double r = ::sqrt (static_cast(lD2)); - v[ix][iy] = filter.response (r); + long lD2 = ((ix - iXCenter) * (ix - iXCenter)) + ((iy - iYCenter) * (iy - iYCenter)); + double r = ::sqrt (static_cast(lD2)) * dInputScale; + v[ix][iy] = filter.response (r) * dOutputScale; } #else int hx = (m_nx - 1) / 2; @@ -356,18 +385,29 @@ ImageFile::subtractImages (const ImageFile& rRHS, ImageFile& result) const return false; } + if (isComplex() || rRHS.isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + ImageFileArrayConst vLHS = getArray(); + ImageFileArrayConst vLHSImag = getImaginaryArray(); ImageFileArrayConst vRHS = rRHS.getArray(); + ImageFileArrayConst vRHSImag = rRHS.getImaginaryArray(); ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); for (unsigned int ix = 0; ix < m_nx; ix++) { - ImageFileColumnConst in1 = vLHS[ix]; - ImageFileColumnConst in2 = vRHS[ix]; - ImageFileColumn out = vResult[ix]; - for (unsigned int iy = 0; iy < m_ny; iy++) - *out++ = *in1++ - *in2++; + for (unsigned int iy = 0; iy < m_ny; iy++) { + vResult[ix][iy] = vLHS[ix][iy] - vRHS[ix][iy]; + if (result.isComplex()) { + vResultImag[ix][iy] = 0; + if (isComplex()) + vResultImag[ix][iy] += vLHSImag[ix][iy]; + if (rRHS.isComplex()) + vResultImag[ix][iy] -= vRHSImag[ix][iy]; + } + } } - + return true; } @@ -379,16 +419,27 @@ ImageFile::addImages (const ImageFile& rRHS, ImageFile& result) const return false; } + if (isComplex() || rRHS.isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + ImageFileArrayConst vLHS = getArray(); + ImageFileArrayConst vLHSImag = getImaginaryArray(); ImageFileArrayConst vRHS = rRHS.getArray(); + ImageFileArrayConst vRHSImag = rRHS.getImaginaryArray(); ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); for (unsigned int ix = 0; ix < m_nx; ix++) { - ImageFileColumnConst in1 = vLHS[ix]; - ImageFileColumnConst in2 = vRHS[ix]; - ImageFileColumn out = vResult[ix]; - for (unsigned int iy = 0; iy < m_ny; iy++) - *out++ = *in1++ + *in2++; + for (unsigned int iy = 0; iy < m_ny; iy++) { + vResult[ix][iy] = vLHS[ix][iy] + vRHS[ix][iy]; + if (result.isComplex()) { + vResultImag[ix][iy] = 0; + if (isComplex()) + vResultImag[ix][iy] += vLHSImag[ix][iy]; + if (rRHS.isComplex()) + vResultImag[ix][iy] += vRHSImag[ix][iy]; + } + } } return true; @@ -402,18 +453,34 @@ ImageFile::multiplyImages (const ImageFile& rRHS, ImageFile& result) const return false; } + if (isComplex() || rRHS.isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + ImageFileArrayConst vLHS = getArray(); + ImageFileArrayConst vLHSImag = getImaginaryArray(); ImageFileArrayConst vRHS = rRHS.getArray(); + ImageFileArrayConst vRHSImag = rRHS.getImaginaryArray(); ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); for (unsigned int ix = 0; ix < m_nx; ix++) { - ImageFileColumnConst in1 = vLHS[ix]; - ImageFileColumnConst in2 = vRHS[ix]; - ImageFileColumn out = vResult[ix]; - for (unsigned int iy = 0; iy < m_ny; iy++) - *out++ = *in1++ * *in2++; + for (unsigned int iy = 0; iy < m_ny; iy++) { + if (result.isComplex()) { + std::complex cLHS (vLHS[ix][iy], 0); + if (isComplex()) + cLHS.imag (vLHSImag[ix][iy]); + std::complex cRHS (vRHS[ix][iy], 0); + if (rRHS.isComplex()) + cRHS.imag (vRHSImag[ix][iy]); + std::complex cResult = cLHS * cRHS; + vResult[ix][iy] = cResult.real(); + vResultImag[ix][iy] = cResult.imag(); + } else + vResult[ix][iy] = vLHS[ix][iy] * vRHS[ix][iy]; + } } + return true; } @@ -425,22 +492,38 @@ ImageFile::divideImages (const ImageFile& rRHS, ImageFile& result) const return false; } + if (isComplex() || rRHS.isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + ImageFileArrayConst vLHS = getArray(); + ImageFileArrayConst vLHSImag = getImaginaryArray(); ImageFileArrayConst vRHS = rRHS.getArray(); + ImageFileArrayConst vRHSImag = rRHS.getImaginaryArray(); ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); for (unsigned int ix = 0; ix < m_nx; ix++) { - ImageFileColumnConst in1 = vLHS[ix]; - ImageFileColumnConst in2 = vRHS[ix]; - ImageFileColumn out = vResult[ix]; for (unsigned int iy = 0; iy < m_ny; iy++) { - if (*in2 != 0.) - *out++ = *in1++ / *in2++; - else - *out++ = 0; + if (result.isComplex()) { + std::complex cLHS (vLHS[ix][iy], 0); + if (isComplex()) + cLHS.imag (vLHSImag[ix][iy]); + std::complex cRHS (vRHS[ix][iy], 0); + if (rRHS.isComplex()) + cRHS.imag (vRHSImag[ix][iy]); + std::complex cResult = cLHS / cRHS; + vResult[ix][iy] = cResult.real(); + vResultImag[ix][iy] = cResult.imag(); + } else { + if (vRHS != 0) + vResult[ix][iy] = vLHS[ix][iy] / vRHS[ix][iy]; + else + vResult[ix][iy] = 0; + } } } + return true; } @@ -453,6 +536,9 @@ ImageFile::invertPixelValues (ImageFile& result) const return false; } + if (isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + ImageFileArrayConst vLHS = getArray(); ImageFileArray vResult = result.getArray(); @@ -473,20 +559,40 @@ ImageFile::sqrt (ImageFile& result) const sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]"); return false; } + + if (isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + bool bComplexOutput = result.isComplex(); ImageFileArrayConst vLHS = getArray(); + if (! bComplexOutput) // check if should convert to complex output + for (unsigned int ix = 0; ix < m_nx; ix++) + for (unsigned int iy = 0; iy < m_ny; iy++) + if (! bComplexOutput && vLHS[ix][iy] < 0) { + result.convertRealToComplex(); + bComplexOutput = true; + break; + } + + ImageFileArrayConst vLHSImag = getImaginaryArray(); ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); for (unsigned int ix = 0; ix < m_nx; ix++) { - ImageFileColumnConst in = vLHS[ix]; - ImageFileColumn out = vResult[ix]; - for (unsigned int iy = 0; iy < m_ny; iy++) - if (*in < 0) - *out++ = -::sqrt(-*in++); - else - *out++ = ::sqrt(*in++); + for (unsigned int iy = 0; iy < m_ny; iy++) { + if (result.isComplex()) { + std::complex cLHS (vLHS[ix][iy], 0); + if (isComplex()) + cLHS.imag (vLHSImag[ix][iy]); + std::complex cResult = std::sqrt(cLHS); + vResult[ix][iy] = cResult.real(); + vResultImag[ix][iy] = cResult.imag(); + } else + vResult[ix][iy] = ::sqrt (vLHS[ix][iy]); + } } + return true; } @@ -498,19 +604,29 @@ ImageFile::log (ImageFile& result) const return false; } + if (isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + ImageFileArrayConst vLHS = getArray(); + ImageFileArrayConst vLHSImag = getImaginaryArray(); ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); for (unsigned int ix = 0; ix < m_nx; ix++) { - ImageFileColumnConst in = vLHS[ix]; - ImageFileColumn out = vResult[ix]; - for (unsigned int iy = 0; iy < m_ny; iy++) - if (*in <= 0) - *out++ = 0; - else - *out++ = ::log(*in++); + for (unsigned int iy = 0; iy < m_ny; iy++) { + if (result.isComplex()) { + std::complex cLHS (vLHS[ix][iy], 0); + if (isComplex()) + cLHS.imag (vLHSImag[ix][iy]); + std::complex cResult = std::log (cLHS); + vResult[ix][iy] = cResult.real(); + vResultImag[ix][iy] = cResult.imag(); + } else + vResult[ix][iy] = ::log (vLHS[ix][iy]); + } } + return true; } @@ -521,95 +637,69 @@ ImageFile::exp (ImageFile& result) const sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]"); return false; } - + + if (isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + ImageFileArrayConst vLHS = getArray(); + ImageFileArrayConst vLHSImag = getImaginaryArray(); ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); for (unsigned int ix = 0; ix < m_nx; ix++) { - ImageFileColumnConst in = vLHS[ix]; - ImageFileColumn out = vResult[ix]; - for (unsigned int iy = 0; iy < m_ny; iy++) - *out++ = ::exp (*in++); + for (unsigned int iy = 0; iy < m_ny; iy++) { + if (result.isComplex()) { + std::complex cLHS (vLHS[ix][iy], 0); + if (isComplex()) + cLHS.imag (vLHSImag[ix][iy]); + std::complex cResult = std::exp (cLHS); + vResult[ix][iy] = cResult.real(); + vResultImag[ix][iy] = cResult.imag(); + } else + vResult[ix][iy] = ::exp (vLHS[ix][iy]); + } } + return true; } -namespace ProcessImage { - -void -shuffleFourierToNaturalOrder (ImageFile& im) +bool +ImageFile::scaleImage (ImageFile& result) const { - ImageFileArray vReal = im.getArray(); - ImageFileArray vImag = im.getImaginaryArray(); - unsigned int ix, iy; - unsigned int nx = im.nx(); - unsigned int ny = im.ny(); - - // shuffle each column - for (ix = 0; ix < nx; ix++) { - ProcessSignal::shuffleFourierToNaturalOrder (vReal[ix], ny); - if (im.isComplex()) - ProcessSignal::shuffleFourierToNaturalOrder (vImag[ix], ny); - } + unsigned int nx = m_nx; + unsigned int ny = m_ny; + unsigned int newNX = result.nx(); + unsigned int newNY = result.ny(); - // shuffle each row - float* pRow = new float [nx]; - for (iy = 0; iy < ny; iy++) { - for (ix = 0; ix < nx; ix++) - pRow[ix] = vReal[ix][iy]; - ProcessSignal::shuffleFourierToNaturalOrder (pRow, nx); - for (ix = 0; ix < nx; ix++) - vReal[ix][iy] = pRow[ix]; - if (im.isComplex()) { - for (ix = 0; ix < nx; ix++) - pRow[ix] = vImag[ix][iy]; - ProcessSignal::shuffleFourierToNaturalOrder (pRow, nx);; - for (ix = 0; ix < nx; ix++) - vImag[ix][iy] = pRow[ix]; - } - } - delete pRow; -} - -void -shuffleNaturalToFourierOrder (ImageFile& im) -{ - ImageFileArray vReal = im.getArray(); - ImageFileArray vImag = im.getImaginaryArray(); - unsigned int ix, iy; - unsigned int nx = im.nx(); - unsigned int ny = im.ny(); - - // shuffle each x column - for (ix = 0; ix < nx; ix++) { - ProcessSignal::shuffleNaturalToFourierOrder (vReal[ix], ny); - if (im.isComplex()) - ProcessSignal::shuffleNaturalToFourierOrder (vImag[ix], ny); - } + double dXScale = static_cast(newNX) / static_cast(nx); + double dYScale = static_cast(newNY) / static_cast(ny); + + if (isComplex() && ! result.isComplex()) + result.convertRealToComplex(); - // shuffle each y row - float* pRow = new float [nx]; - for (iy = 0; iy < ny; iy++) { - for (ix = 0; ix < nx; ix++) - pRow[ix] = vReal[ix][iy]; - ProcessSignal::shuffleNaturalToFourierOrder (pRow, nx); - for (ix = 0; ix < nx; ix++) - vReal[ix][iy] = pRow[ix]; - if (im.isComplex()) { - for (ix = 0; ix < nx; ix++) - pRow[ix] = vImag[ix][iy]; - ProcessSignal::shuffleNaturalToFourierOrder (pRow, nx); - for (ix = 0; ix < nx; ix++) - vImag[ix][iy] = pRow[ix]; + ImageFileArrayConst vReal = getArray(); + ImageFileArrayConst vImag = getImaginaryArray(); + ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); + + for (unsigned int ix = 0; ix < newNX; ix++) { + for (unsigned int iy = 0; iy < newNY; iy++) { + unsigned int scaleNX = static_cast (ix / dXScale); + unsigned int scaleNY = static_cast (iy / dYScale); + vResult[ix][iy] = vReal[scaleNX][scaleNY]; + if (result.isComplex()) { + if (isComplex()) + vResultImag[ix][iy] = vImag[scaleNX][scaleNY]; + else + vResultImag[ix][iy] = 0; + } } } - delete [] pRow; + + return true; } - -}; // namespace ProcessIamge - #ifdef HAVE_FFTW bool ImageFile::fft (ImageFile& result) const @@ -620,7 +710,7 @@ ImageFile::fft (ImageFile& result) const } if (result.dataType() == Array2dFile::DATA_TYPE_REAL) { - if (! result.reallocRealToComplex ()) + if (! result.convertRealToComplex ()) return false; } @@ -660,7 +750,7 @@ ImageFile::fft (ImageFile& result) const delete in; - ProcessImage::shuffleFourierToNaturalOrder (result); + Fourier::shuffleFourierToNaturalOrder (result); return true; } @@ -675,7 +765,7 @@ ImageFile::ifft (ImageFile& result) const } if (result.dataType() == Array2dFile::DATA_TYPE_REAL) { - if (! result.reallocRealToComplex ()) + if (! result.convertRealToComplex ()) return false; } @@ -693,7 +783,7 @@ ImageFile::ifft (ImageFile& result) const vImagResult[ix][iy] = 0; } - ProcessImage::shuffleNaturalToFourierOrder (result); + Fourier::shuffleNaturalToFourierOrder (result); fftw_complex* in = new fftw_complex [m_nx * m_ny]; @@ -735,10 +825,9 @@ ImageFile::fourier (ImageFile& result) const return false; } - if (result.dataType() == Array2dFile::DATA_TYPE_REAL) { - if (! result.reallocRealToComplex ()) + if (! result.isComplex()) + if (! result.convertRealToComplex ()) return false; - } ImageFileArrayConst vLHS = getArray(); ImageFileArrayConst vLHSImag = getImaginaryArray(); @@ -787,33 +876,22 @@ ImageFile::fourier (ImageFile& result) const complexOut[ix][iy] = complexOutRow[ix]; } delete [] pX; - - // shuffle each column - for (ix = 0; ix < m_nx; ix++) - ProcessSignal::shuffleFourierToNaturalOrder (complexOut[ix], m_ny); - - // shuffle each row - for (iy = 0; iy < m_ny; iy++) { - for (ix = 0; ix < m_nx; ix++) - complexOutRow[ix] = complexOut[ix][iy]; - ProcessSignal::shuffleFourierToNaturalOrder (complexOutRow, m_nx);; - for (ix = 0; ix < m_nx; ix++) - complexOut[ix][iy] = complexOutRow[ix]; - - } delete [] complexOutRow; - + for (ix = 0; ix < m_nx; ix++) for (iy = 0; iy < m_ny; iy++) { vRealResult[ix][iy] = complexOut[ix][iy].real(); vImagResult[ix][iy] = complexOut[ix][iy].imag(); } - for (ix = 0; ix < m_nx; ix++) - delete [] complexOut[ix]; - delete [] complexOut; + Fourier::shuffleFourierToNaturalOrder (result); + + // delete complexOut matrix + for (ix = 0; ix < m_nx; ix++) + delete [] complexOut[ix]; + delete [] complexOut; - return true; + return true; } bool @@ -825,50 +903,40 @@ ImageFile::inverseFourier (ImageFile& result) const } if (result.dataType() == Array2dFile::DATA_TYPE_REAL) { - if (! result.reallocRealToComplex ()) + if (! result.convertRealToComplex ()) return false; } ImageFileArrayConst vLHSReal = getArray(); ImageFileArrayConst vLHSImag = getImaginaryArray(); + ImageFileArray vRealResult = result.getArray(); + ImageFileArray vImagResult = result.getImaginaryArray(); unsigned int ix, iy; - // alloc 2d complex output matrix CTSimComplex** complexOut = new CTSimComplex* [m_nx]; for (ix = 0; ix < m_nx; ix++) complexOut[ix] = new CTSimComplex [m_ny]; - // put input image into complexOut + // put input image into result for (ix = 0; ix < m_nx; ix++) for (iy = 0; iy < m_ny; iy++) { - complexOut[ix][iy].real (vLHSReal[ix][iy]); + vRealResult[ix][iy] = vLHSReal[ix][iy]; if (isComplex()) - complexOut[ix][iy].imag (vLHSImag[ix][iy]); + vImagResult[ix][iy] = vLHSImag[ix][iy]; else - complexOut[ix][iy].imag (0); + vImagResult[ix][iy] = 0; } - // shuffle each x column - for (ix = 0; ix < m_nx; ix++) - ProcessSignal::shuffleNaturalToFourierOrder (complexOut[ix], m_ny); - - // shuffle each y row - CTSimComplex* pComplexRow = new CTSimComplex [m_nx]; - for (iy = 0; iy < m_ny; iy++) { - for (ix = 0; ix < m_nx; ix++) - pComplexRow[ix] = complexOut[ix][iy]; - ProcessSignal::shuffleNaturalToFourierOrder (pComplexRow, m_nx); - for (ix = 0; ix < m_nx; ix++) - complexOut[ix][iy] = pComplexRow[ix]; - } - delete [] pComplexRow; + Fourier::shuffleNaturalToFourierOrder (result); // ifourier each x column CTSimComplex* pCol = new CTSimComplex [m_ny]; for (ix = 0; ix < m_nx; ix++) { - for (iy = 0; iy < m_ny; iy++) - pCol[iy] = complexOut[ix][iy]; + for (iy = 0; iy < m_ny; iy++) { + pCol[iy].real (vRealResult[ix][iy]); + pCol[iy].imag (vImagResult[ix][iy]); + } ProcessSignal::finiteFourierTransform (pCol, complexOut[ix], m_ny, ProcessSignal::BACKWARD); } delete [] pCol; @@ -886,8 +954,6 @@ ImageFile::inverseFourier (ImageFile& result) const delete [] complexInRow; delete [] complexOutRow; - ImageFileArray vRealResult = result.getArray(); - ImageFileArray vImagResult = result.getImaginaryArray(); for (ix = 0; ix < m_nx; ix++) for (iy = 0; iy < m_ny; iy++) { vRealResult[ix][iy] = complexOut[ix][iy].real(); @@ -913,8 +979,8 @@ ImageFile::magnitude (ImageFile& result) const ImageFileArray vReal = getArray(); ImageFileArray vImag = getImaginaryArray(); - ImageFileArray vRealResult = result.getArray(); + for (unsigned int ix = 0; ix < m_nx; ix++) for (unsigned int iy = 0; iy < m_ny; iy++) { if (isComplex()) @@ -924,7 +990,7 @@ ImageFile::magnitude (ImageFile& result) const } if (result.isComplex()) - result.reallocComplexToReal(); + result.convertComplexToReal(); return true; } @@ -939,8 +1005,8 @@ ImageFile::phase (ImageFile& result) const ImageFileArray vReal = getArray(); ImageFileArray vImag = getImaginaryArray(); - ImageFileArray vRealResult = result.getArray(); + for (unsigned int ix = 0; ix < m_nx; ix++) for (unsigned int iy = 0; iy < m_ny; iy++) { if (isComplex()) @@ -950,7 +1016,7 @@ ImageFile::phase (ImageFile& result) const } if (result.isComplex()) - result.reallocComplexToReal(); + result.convertComplexToReal(); return true; } @@ -963,24 +1029,92 @@ ImageFile::square (ImageFile& result) const return false; } + if (isComplex() && ! result.isComplex()) + result.convertRealToComplex(); + ImageFileArrayConst vLHS = getArray(); + ImageFileArrayConst vLHSImag = getImaginaryArray(); ImageFileArray vResult = result.getArray(); + ImageFileArray vResultImag = result.getImaginaryArray(); for (unsigned int ix = 0; ix < m_nx; ix++) { - ImageFileColumnConst in = vLHS[ix]; - ImageFileColumn out = vResult[ix]; for (unsigned int iy = 0; iy < m_ny; iy++) { - *out++ = *in * *in; - in++; + if (result.isComplex()) { + std::complex cLHS (vLHS[ix][iy], 0); + if (isComplex()) + cLHS.imag (vLHSImag[ix][iy]); + std::complex cResult = cLHS * cLHS; + vResult[ix][iy] = cResult.real(); + vResultImag[ix][iy] = cResult.imag(); + } else + vResult[ix][iy] = vLHS[ix][iy] * vLHS[ix][iy]; } } + return true; } +int +ImageFile::convertFormatNameToID (const char* const formatName) +{ + int formatID = FORMAT_INVALID; -void -ImageFile::writeImagePGM (const char *outfile, int nxcell, int nycell, double densmin, double densmax) + for (int i = 0; i < s_iFormatCount; i++) + if (strcasecmp (formatName, s_aszFormatName[i]) == 0) { + formatID = i; + break; + } + + return (formatID); +} + +const char* +ImageFile::convertFormatIDToName (int formatID) +{ + static const char *formatName = ""; + + if (formatID >= 0 && formatID < s_iFormatCount) + return (s_aszFormatName[formatID]); + + return (formatName); +} + +const char* +ImageFile::convertFormatIDToTitle (const int formatID) +{ + static const char *formatTitle = ""; + + if (formatID >= 0 && formatID < s_iFormatCount) + return (s_aszFormatTitle[formatID]); + + return (formatTitle); +} + +bool +ImageFile::exportImage (const char* const pszFormat, const char* const pszFilename, int nxcell, int nycell, double densmin, double densmax) +{ + int iFormatID = convertFormatNameToID (pszFormat); + if (iFormatID == FORMAT_INVALID) { + sys_error (ERR_SEVERE, "Invalid format %s [ImageFile::exportImage]", pszFormat); + return false; + } + + if (iFormatID == FORMAT_PGM) + return writeImagePGM (pszFilename, nxcell, nycell, densmin, densmax); + else if (iFormatID == FORMAT_PGMASCII) + return writeImagePGMASCII (pszFilename, nxcell, nycell, densmin, densmax); + else if (iFormatID == FORMAT_PNG) + return writeImagePNG (pszFilename, 8, nxcell, nycell, densmin, densmax); + else if (iFormatID == FORMAT_PNG16) + return writeImagePNG (pszFilename, 16, nxcell, nycell, densmin, densmax); + + sys_error (ERR_SEVERE, "Invalid format %s [ImageFile::exportImage]", pszFormat); + return false; +} + +bool +ImageFile::writeImagePGM (const char* const outfile, int nxcell, int nycell, double densmin, double densmax) { FILE *fp; int nx = m_nx; @@ -990,7 +1124,7 @@ ImageFile::writeImagePGM (const char *outfile, int nxcell, int nycell, double de unsigned char* rowp = new unsigned char [nx * nxcell]; if ((fp = fopen (outfile, "wb")) == NULL) - return; + return false; fprintf(fp, "P5\n"); fprintf(fp, "%d %d\n", nx, ny); @@ -1012,11 +1146,13 @@ ImageFile::writeImagePGM (const char *outfile, int nxcell, int nycell, double de } delete rowp; - fclose(fp); + fclose(fp); + + return true; } -void -ImageFile::writeImagePGMASCII (const char *outfile, int nxcell, int nycell, double densmin, double densmax) +bool +ImageFile::writeImagePGMASCII (const char* const outfile, int nxcell, int nycell, double densmin, double densmax) { FILE *fp; int nx = m_nx; @@ -1026,7 +1162,7 @@ ImageFile::writeImagePGMASCII (const char *outfile, int nxcell, int nycell, doub unsigned char* rowp = new unsigned char [nx * nxcell]; if ((fp = fopen (outfile, "wb")) == NULL) - return; + return false; fprintf(fp, "P2\n"); fprintf(fp, "%d %d\n", nx, ny); @@ -1049,17 +1185,16 @@ ImageFile::writeImagePGMASCII (const char *outfile, int nxcell, int nycell, doub } delete rowp; - fclose(fp); + fclose(fp); + + return true; } #ifdef HAVE_PNG -void -ImageFile::writeImagePNG (const char *outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax) +bool +ImageFile::writeImagePNG (const char* const outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax) { - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; double max_out_level = (1 << bitdepth) - 1; int nx = m_nx; int ny = m_ny; @@ -1067,29 +1202,30 @@ ImageFile::writeImagePNG (const char *outfile, int bitdepth, int nxcell, int nyc unsigned char* rowp = new unsigned char [nx * nxcell * (bitdepth / 8)]; - if ((fp = fopen (outfile, "wb")) == NULL) - return; + FILE *fp = fopen (outfile, "wb"); + if (! fp) + return false; - png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (! png_ptr) - return; + return false; - info_ptr = png_create_info_struct(png_ptr); + png_infop info_ptr = png_create_info_struct (png_ptr); if (! info_ptr) { - png_destroy_write_struct(&png_ptr, (png_infopp) NULL); - fclose(fp); - return; + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + fclose (fp); + return false; } - if (setjmp(png_ptr->jmpbuf)) { - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); - return; + if (setjmp (png_ptr->jmpbuf)) { + png_destroy_write_struct (&png_ptr, &info_ptr); + fclose (fp); + return false; } png_init_io(png_ptr, fp); - png_set_IHDR(png_ptr, info_ptr, nx * nxcell, ny * nycell, bitdepth, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT); + png_set_IHDR (png_ptr, info_ptr, nx * nxcell, ny * nycell, bitdepth, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); for (int irow = ny - 1; irow >= 0; irow--) { @@ -1115,11 +1251,13 @@ ImageFile::writeImagePNG (const char *outfile, int bitdepth, int nxcell, int nyc png_write_rows (png_ptr, &row_pointer, 1); } - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); + png_write_end (png_ptr, info_ptr); + png_destroy_write_struct (&png_ptr, &info_ptr); delete rowp; - fclose(fp); + fclose(fp); + + return true; } #endif @@ -1127,21 +1265,17 @@ ImageFile::writeImagePNG (const char *outfile, int bitdepth, int nxcell, int nyc #include "gd.h" static const int N_GRAYSCALE=256; -void -ImageFile::writeImageGIF (const char *outfile, int nxcell, int nycell, double densmin, double densmax) +bool +ImageFile::writeImageGIF (const char* const outfile, int nxcell, int nycell, double densmin, double densmax) { - gdImagePtr gif; - FILE *out; int gs_indices[N_GRAYSCALE]; int nx = m_nx; int ny = m_ny; ImageFileArray v = getArray(); - unsigned char rowp [nx * nxcell]; - if (rowp == NULL) - return; + unsigned char* rowp = new unsigned char [nx * nxcell]; - gif = gdImageCreate(nx * nxcell, ny * nycell); + gdImagePtr gif = gdImageCreate(nx * nxcell, ny * nycell); for (int i = 0; i < N_GRAYSCALE; i++) gs_indices[i] = gdImageColorAllocate(gif, i, i, i); @@ -1161,13 +1295,18 @@ ImageFile::writeImageGIF (const char *outfile, int nxcell, int nycell, double de } } - if ((out = fopen(outfile,"w")) == NULL) { + FILE *out; + if ((out = fopen (outfile,"w")) == NULL) { sys_error(ERR_FATAL, "Error opening output file %s for writing", outfile); - return (1); + return false; } gdImageGif(gif,out); fclose(out); - gdImageDestroy(gif); + gdImageDestroy(gif); + + delete rowp; + + return true; } #endif diff --git a/libctsim/procsignal.cpp b/libctsim/procsignal.cpp index 8c45da4..41895ac 100644 --- a/libctsim/procsignal.cpp +++ b/libctsim/procsignal.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: procsignal.cpp,v 1.12 2001/01/01 10:14:34 kevin Exp $ +** $Id: procsignal.cpp,v 1.13 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 @@ -189,7 +189,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw pEZPlot->plot (pSGP); } #endif - shuffleNaturalToFourierOrder (adFrequencyFilter, m_nFilterPoints); + Fourier::shuffleNaturalToFourierOrder (adFrequencyFilter, m_nFilterPoints); #ifdef HAVE_SGP if (pEZPlot && m_traceLevel >= Trace::TRACE_PLOT) { pEZPlot->ezset ("title Filter Response: Fourier Order"); @@ -210,7 +210,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw pEZPlot->plot (pSGP); } #endif - shuffleFourierToNaturalOrder (m_adFilter, m_nFilterPoints); + Fourier::shuffleFourierToNaturalOrder (m_adFilter, m_nFilterPoints); #ifdef HAVE_SGP if (pEZPlot && m_traceLevel >= Trace::TRACE_PLOT) { pEZPlot->ezset ("title Inverse Fourier Frequency: Natural Order"); @@ -304,7 +304,7 @@ ProcessSignal::init (const int idFilter, const int idFilterMethod, double dBandw pEZPlot->plot (pSGP); } #endif - shuffleNaturalToFourierOrder (m_adFilter, m_nFilterPoints); + Fourier::shuffleNaturalToFourierOrder (m_adFilter, m_nFilterPoints); #ifdef HAVE_SGP if (pEZPlot && m_traceLevel >= Trace::TRACE_PLOT) { pEZPlot->ezset ("title Filter Filter: Fourier Order"); @@ -855,200 +855,3 @@ ProcessSignal::finiteFourierTransform (const std::complex input[], doubl } } -// Odd Number of Points -// Natural Frequency Order: -(n-1)/2...-1,0,1...(n-1)/2 -// Fourier Frequency Order: 0, 1..(n-1)/2,-(n-1)/2...-1 -// Even Number of Points -// Natural Frequency Order: -n/2...-1,0,1...((n/2)-1) -// Fourier Frequency Order: 0,1...((n/2)-1),-n/2...-1 - -void -ProcessSignal::shuffleNaturalToFourierOrder (double* pdVector, const int n) -{ - double* pdTemp = new double [n]; - int i; - if (n % 2) { // Odd - int iHalfN = (n - 1) / 2; - - pdTemp[0] = pdVector[iHalfN]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + 1] = pdVector[i + 1 + iHalfN]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + iHalfN + 1] = pdVector[i]; - } else { // Even - int iHalfN = n / 2; - pdTemp[0] = pdVector[iHalfN]; -#if USE_BROKEN_SHUFFLE - for (i = 0; i < iHalfN; i++) - pdTemp[i + 1] = pdVector[i + iHalfN]; - for (i = 0; i < iHalfN - 1; i++) - pdTemp[i + iHalfN + 1] = pdVector[i]; -#else - for (i = 0; i < iHalfN - 1; i++) - pdTemp[i + 1] = pdVector[i + iHalfN + 1]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + iHalfN] = pdVector[i]; -#endif - } - - for (i = 0; i < n; i++) - pdVector[i] = pdTemp[i]; - delete pdTemp; -} - -void -ProcessSignal::shuffleNaturalToFourierOrder (std::complex* pdVector, const int n) -{ - std::complex* pdTemp = new std::complex [n]; - int i; - if (n % 2) { // Odd - int iHalfN = (n - 1) / 2; - - pdTemp[0] = pdVector[iHalfN]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + 1] = pdVector[i + 1 + iHalfN]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + iHalfN + 1] = pdVector[i]; - } else { // Even - int iHalfN = n / 2; - pdTemp[0] = pdVector[iHalfN]; -#if USE_BROKEN_SHUFFLE - for (i = 0; i < iHalfN; i++) - pdTemp[i + 1] = pdVector[i + iHalfN]; - for (i = 0; i < iHalfN - 1; i++) - pdTemp[i + iHalfN + 1] = pdVector[i]; -#else - for (i = 0; i < iHalfN - 1; i++) - pdTemp[i + 1] = pdVector[i + iHalfN + 1]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + iHalfN] = pdVector[i]; -#endif - } - - for (i = 0; i < n; i++) - pdVector[i] = pdTemp[i]; - delete [] pdTemp; -} - - -void -ProcessSignal::shuffleNaturalToFourierOrder (float* pdVector, const int n) -{ - float* pdTemp = new float [n]; - int i; - if (n % 2) { // Odd - int iHalfN = (n - 1) / 2; - - pdTemp[0] = pdVector[iHalfN]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + 1] = pdVector[i + 1 + iHalfN]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + iHalfN + 1] = pdVector[i]; - } else { // Even - int iHalfN = n / 2; - pdTemp[0] = pdVector[iHalfN]; -#if USE_BROKEN_SHUFFLE - for (i = 0; i < iHalfN; i++) - pdTemp[i + 1] = pdVector[i + iHalfN]; - for (i = 0; i < iHalfN - 1; i++) - pdTemp[i + iHalfN + 1] = pdVector[i]; -#else - for (i = 0; i < iHalfN - 1; i++) - pdTemp[i + 1] = pdVector[i + iHalfN + 1]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + iHalfN] = pdVector[i]; -#endif - } - - for (i = 0; i < n; i++) - pdVector[i] = pdTemp[i]; - delete pdTemp; -} - - - -void -ProcessSignal::shuffleFourierToNaturalOrder (double* pdVector, const int n) -{ - double* pdTemp = new double [n]; - int i; - if (n % 2) { // Odd - int iHalfN = (n - 1) / 2; - - pdTemp[iHalfN] = pdVector[0]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + 1 + iHalfN] = pdVector[i + 1]; - for (i = 0; i < iHalfN; i++) - pdTemp[i] = pdVector[i + iHalfN + 1]; - } else { // Even - int iHalfN = n / 2; - pdTemp[iHalfN] = pdVector[0]; - for (i = 0; i < iHalfN; i++) - pdTemp[i] = pdVector[i + iHalfN]; - for (i = 0; i < iHalfN - 1; i++) - pdTemp[i + iHalfN + 1] = pdVector[i+1]; - } - - for (i = 0; i < n; i++) - pdVector[i] = pdTemp[i]; - delete pdTemp; -} - - -void -ProcessSignal::shuffleFourierToNaturalOrder (std::complex* pdVector, const int n) -{ - std::complex* pdTemp = new std::complex [n]; - int i; - if (n % 2) { // Odd - int iHalfN = (n - 1) / 2; - - pdTemp[iHalfN] = pdVector[0]; - for (i = 0; i < iHalfN; i++) - pdTemp[i + 1 + iHalfN] = pdVector[i + 1]; - for (i = 0; i < iHalfN; i++) - pdTemp[i] = pdVector[i + iHalfN + 1]; - } else { // Even - int iHalfN = n / 2; - pdTemp[iHalfN] = pdVector[0]; - for (i = 0; i < iHalfN; i++) - pdTemp[i] = pdVector[i + iHalfN]; - for (i = 0; i < iHalfN - 1; i++) - pdTemp[i + iHalfN + 1] = pdVector[i+1]; - } - - for (i = 0; i < n; i++) - pdVector[i] = pdTemp[i]; - delete [] pdTemp; -} - - - - -void -ProcessSignal::shuffleFourierToNaturalOrder (float* pVector, const int n) -{ - float* pTemp = new float [n]; - int i; - if (n % 2) { // Odd - int iHalfN = (n - 1) / 2; - - pTemp[iHalfN] = pVector[0]; - for (i = 0; i < iHalfN; i++) - pTemp[i + 1 + iHalfN] = pVector[i + 1]; - for (i = 0; i < iHalfN; i++) - pTemp[i] = pVector[i + iHalfN + 1]; - } else { // Even - int iHalfN = n / 2; - pTemp[iHalfN] = pVector[0]; - for (i = 0; i < iHalfN; i++) - pTemp[i] = pVector[i + iHalfN]; - for (i = 0; i < iHalfN - 1; i++) - pTemp[i + iHalfN + 1] = pVector[i+1]; - } - - for (i = 0; i < n; i++) - pVector[i] = pTemp[i]; - delete [] pTemp; -} - diff --git a/libctsupport/mathfuncs.cpp b/libctsupport/mathfuncs.cpp index 3604b2f..c9b18ac 100644 --- a/libctsupport/mathfuncs.cpp +++ b/libctsupport/mathfuncs.cpp @@ -2,7 +2,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: mathfuncs.cpp,v 1.5 2001/01/01 10:14:34 kevin Exp $ +** $Id: mathfuncs.cpp,v 1.6 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 @@ -93,15 +93,12 @@ vectorNumericStatistics (std::vector vec, const int nPoints, double& min min = vec[0]; max = vec[0]; int i; - int iMinPos = 0; for (i = 0; i < nPoints; i++) { double v = vec[i]; if (v > max) max = v; - if (v < min) { + if (v < min) min = v; - iMinPos = i; - } mean += v; } mean /= nPoints; diff --git a/libctsupport/plotfile.cpp b/libctsupport/plotfile.cpp index 16336ef..ef8d264 100644 --- a/libctsupport/plotfile.cpp +++ b/libctsupport/plotfile.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: plotfile.cpp,v 1.7 2000/12/29 20:09:46 kevin Exp $ +** $Id: plotfile.cpp,v 1.8 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 @@ -40,7 +40,7 @@ PlotFile::PlotFile (int nCurves, int nRecords) { initHeaders (); - setCurveSize (nCurves, nRecords); + setCurveSize (nCurves, nRecords); } PlotFile::PlotFile () @@ -57,7 +57,8 @@ PlotFile::initHeaders () { m_iNumColumns = 0; m_iNumRecords = 0; - m_strDate = ""; + time_t currentTime = time (NULL); + m_strDate = ctime (¤tTime); m_vecStrDescriptions.clear(); m_vecStrEzsetCommands.clear(); } @@ -221,11 +222,32 @@ PlotFile::headerRead (std::iostream& fs) fs.seekg (0); bool bFinishedHeaders = false; + fs >> m_iNumColumns; + fs >> m_iNumRecords; + + if (fs.fail() || m_iNumColumns == 0 || m_iNumRecords == 0) + return false; + while (! bFinishedHeaders && ! fs.eof() && ! fs.fail()) { char line[1024]; fs.getline (line, sizeof(line)); - if (strstr (line, "") != NULL) + int iSP = 0; + while (line[iSP] == ' ') + iSP++; + if (line[iSP] == '\n' || ! line[iSP]) + ; + else if (line[iSP] == '#') { + iSP++; + while (line[iSP] == ' ') + iSP++; + if (line[iSP] == '\n' || ! line[iSP]) + ; + else + addDescription (&line[iSP]); + } else if (strstr (&line[iSP], "") != NULL) { bFinishedHeaders = true; + } else + addEzsetCommand (&line[iSP]); } return ! fs.fail(); @@ -241,27 +263,18 @@ PlotFile::headerWrite (std::iostream& fs) } fs.seekp (0); - fs << "\n"; - - int iNEzset = m_vecStrEzsetCommands.size(); - if (iNEzset > 0) { - fs << "\n"; - for (int i = 0; i < iNEzset; i++) + fs << m_iNumColumns << " " << m_iNumRecords << "\n"; + + int i; + for (i = 0; i < m_vecStrEzsetCommands.size(); i++) fs << m_vecStrEzsetCommands[i] << "\n"; - fs << "\n"; - } + + for (i = 0; i < m_vecStrDescriptions.size(); i++) + fs << "# " << m_vecStrDescriptions[i] << "\n"; if (! m_strDate.empty()) - fs << "" << m_strDate << "\n"; - - int iNDesc = m_vecStrDescriptions.size(); - if (iNDesc > 0) { - fs << "\n"; - for (int i = 0; i < iNDesc; i++) - fs << m_vecStrDescriptions[i] << "\n"; - fs << "\n"; - } - + fs << "# Date: " << m_strDate << "\n"; + return ! fs.fail(); } @@ -299,8 +312,6 @@ PlotFile::columnsRead (std::iostream& fs) return false; } - return ! fs.fail(); - if (m_iNumColumns == 0 || m_iNumRecords == 0) { sys_error (ERR_WARNING, "Called PlotFile::columnsRead with 0 columns or records"); return false; @@ -327,5 +338,12 @@ PlotFile::columnsRead (std::iostream& fs) void PlotFile::printHeaders (std::ostream& os) const -{ +{ + os << "EZSet Commands\n"; + for (unsigned int iEZ = 0; iEZ < m_vecStrEzsetCommands.size(); iEZ++) + os << m_vecStrEzsetCommands[iEZ] << "\n"; + + os << "Descriptions\n"; + for (unsigned int iDesc = 0; iDesc < m_vecStrDescriptions.size(); iDesc++) + os << m_vecStrDescriptions[iDesc] << "\n"; } diff --git a/msvc/ctsim/ctsim.plg b/msvc/ctsim/ctsim.plg index fb8f744..8035dcd 100644 --- a/msvc/ctsim/ctsim.plg +++ b/msvc/ctsim/ctsim.plg @@ -3,78 +3,45 @@
 

Build Log

---------------------Configuration: libctsim - Win32 Debug-------------------- +--------------------Configuration: ctsim - Win32 Release--------------------

Command Lines

-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP29A.tmp" with contents +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP22A.tmp" with contents [ -/nologo /G6 /MTd /W3 /Gm /GR /GX /ZI /Od /I "..\..\..\zlib" /I "..\..\INCLUDE" /I "..\..\getopt" /I "..\..\..\lpng108" /I "..\..\..\fftw-2.1.3\fftw" /I "..\..\..\fftw-2.1.3\rfftw" /I "..\..\..\wx2\include" /D "_DEBUG" /D "HAVE_WXWIN" /D "HAVE_STRING_H" /D "HAVE_GETOPT_H" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MSVC" /D "HAVE_FFTW" /D "HAVE_PNG" /D "HAVE_SGP" /D "HAVE_WXWINDOWS" /D "__WXMSW__" /FR"Debug/" /Fp"Debug/libctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c -"C:\ctsim-2.0.6\libctsim\imagefile.cpp" +/nologo /G6 /MT /W3 /GR /GX /O2 /I "." /I "..\..\include" /I "..\..\getopt" /I "..\..\..\lpng108" /I "..\..\..\zlib" /I "..\..\..\fftw-2.1.3\fftw" /I "..\..\..\fftw-2.1.3\rfftw" /I "..\..\..\wx2\include" /D CTSIMVERSION=\"2.5.0\" /D "NDEBUG" /D "__WXWIN__" /D "__WXMSW__" /D "HAVE_SGP" /D "HAVE_PNG" /D "HAVE_WXWINDOWS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "HAVE_STRING_H" /D "HAVE_FFTW" /D "HAVE_RFFTW" /D "HAVE_GETOPT_H" /D "MSVC" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /FR"Release/" /Fp"Release/ctsim.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c +"C:\ctsim-2.0.6\src\views.cpp" ] -Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP29A.tmp" -Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP29B.tmp" with contents +Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP22A.tmp" +Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP22B.tmp" with contents [ -/nologo /out:"Debug\libctsim.lib" -".\Debug\array2dfile.obj" -".\Debug\backprojectors.obj" -".\Debug\clip.obj" -".\Debug\consoleio.obj" -".\Debug\ezplot.obj" -".\Debug\ezset.obj" -".\Debug\ezsupport.obj" -".\Debug\filter.obj" -".\Debug\fnetorderstream.obj" -".\Debug\getopt.obj" -".\Debug\getopt1.obj" -".\Debug\hashtable.obj" -".\Debug\imagefile.obj" -".\Debug\mathfuncs.obj" -".\Debug\phantom.obj" -".\Debug\plotfile.obj" -".\Debug\pol.obj" -".\Debug\procsignal.obj" -".\Debug\projections.obj" -".\Debug\reconstruct.obj" -".\Debug\scanner.obj" -".\Debug\sgp.obj" -".\Debug\strfuncs.obj" -".\Debug\syserror.obj" -".\Debug\trace.obj" -".\Debug\transformmatrix.obj" -".\Debug\xform.obj" +kernel32.lib user32.lib wsock32.lib comctl32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libpng.lib zlib.lib /nologo /subsystem:windows /incremental:no /pdb:"Release/ctsim.pdb" /machine:I386 /out:"Release/ctsim.exe" /libpath:"..\..\..\lpng108\msvc\win32\libpng\lib" /libpath:"..\..\..\lpng108\msvc\win32\zlib\lib" +".\Release\ctsim.obj" +".\Release\dialogs.obj" +".\Release\dlgprojections.obj" +".\Release\dlgreconstruct.obj" +".\Release\docs.obj" +".\Release\views.obj" +".\Release\wx.res" +"\ctsim-2.0.6\msvc\libctsim\Release\libctsim.lib" +"\fftw-2.1.3\Win32\FFTW2st\Release\FFTW2st.lib" +"\fftw-2.1.3\Win32\RFFTW2st\Release\RFFTW2st.lib" +"\wx2\lib\wx.lib" ] -Creating command line "link.exe -lib @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP29B.tmp" +Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP22B.tmp"

Output Window

Compiling... -imagefile.cpp -Creating library... -

---------------------Configuration: ctsim - Win32 Debug-------------------- -

-

Command Lines

-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP29C.tmp" with contents -[ -comctl32.lib winmm.lib rpcrt4.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ../libctsim/Debug/libctsim.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\..\..\lpng108\msvc\win32\libpng\lib_dbg\libpng.lib ..\..\..\lpng108\msvc\win32\zlib\lib_dbg\zlib.lib libcmtd.lib ..\..\..\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib ..\..\..\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib ../../../wx2/lib/wxd.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libcid.lib" /nodefaultlib:"msvcrtd.lib" /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"..\..\..\lpng108\msvc\win32\libpng\lib" /libpath:"..\..\..\lpng108\msvc\win32\zlib\lib" -".\Debug\ctsim.obj" -".\Debug\dialogs.obj" -".\Debug\dlgprojections.obj" -".\Debug\dlgreconstruct.obj" -".\Debug\docs.obj" -".\Debug\views.obj" -".\Debug\wx.res" -"\ctsim-2.0.6\msvc\libctsim\Debug\libctsim.lib" -"\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib" -"\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib" -"\wx2\lib\wxd.lib" -] -Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP29C.tmp" -

Output Window

+views.cpp Linking... +LINK : warning LNK4089: all references to "ADVAPI32.dll" discarded by /OPT:REF +LINK : warning LNK4089: all references to "WSOCK32.dll" discarded by /OPT:REF +Creating command line "bscmake.exe /nologo /o"Release/ctsim.bsc" ".\Release\ctsim.sbr" ".\Release\dialogs.sbr" ".\Release\dlgprojections.sbr" ".\Release\dlgreconstruct.sbr" ".\Release\docs.sbr" ".\Release\views.sbr"" +Creating browse info file... +

Output Window

Results

-ctsim.exe - 0 error(s), 0 warning(s) +ctsim.exe - 0 error(s), 2 warning(s)
diff --git a/msvc/libctsim/libctsim.dsp b/msvc/libctsim/libctsim.dsp index bee0059..3d2fb65 100644 --- a/msvc/libctsim/libctsim.dsp +++ b/msvc/libctsim/libctsim.dsp @@ -138,6 +138,10 @@ SOURCE=..\..\libctsupport\fnetorderstream.cpp # End Source File # Begin Source File +SOURCE=..\..\libctsim\fourier.cpp +# End Source File +# Begin Source File + SOURCE=..\..\getopt\getopt.c # End Source File # Begin Source File @@ -246,6 +250,10 @@ SOURCE=..\..\include\fnetorderstream.h # End Source File # Begin Source File +SOURCE=..\..\include\fourier.h +# End Source File +# Begin Source File + SOURCE=..\..\getopt\getopt.h # End Source File # Begin Source File diff --git a/src/ctsim.cpp b/src/ctsim.cpp index 172cda9..439ae4f 100644 --- a/src/ctsim.cpp +++ b/src/ctsim.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ctsim.cpp,v 1.23 2001/01/01 10:14:34 kevin Exp $ +** $Id: ctsim.cpp,v 1.24 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 @@ -61,23 +61,23 @@ #endif #endif -static const char* rcsindent = "$Id: ctsim.cpp,v 1.23 2001/01/01 10:14:34 kevin Exp $"; +static const char* rcsindent = "$Id: ctsim.cpp,v 1.24 2001/01/02 05:34:57 kevin Exp $"; class CTSimApp* theApp = NULL; struct option CTSimApp::ctsimOptions[] = { - {"help", 0, 0, O_HELP}, - {"version", 0, 0, O_VERSION}, - {0, 0, 0, 0} + {"help", 0, 0, O_HELP}, + {"version", 0, 0, O_VERSION}, + {0, 0, 0, 0} }; IMPLEMENT_APP(CTSimApp) CTSimApp::CTSimApp() - : m_docManager(NULL), m_pFrame(NULL) +: m_docManager(NULL), m_pFrame(NULL) { - theApp = this; + theApp = this; } #ifdef HAVE_SYS_TIME_H @@ -94,86 +94,86 @@ CTSimApp::OnInit() #ifdef HAVE_SETPRIORITY setpriority (PRIO_PROCESS, 0, 15); // set to low scheduling priority #endif - - // process options - while (1) { - int c = getopt_long (argc, argv, "", ctsimOptions, NULL); - if (c == -1) - break; - - switch (c) { - case O_VERSION: - std::cout << rcsindent << std::endl; + + // process options + while (1) { + int c = getopt_long (argc, argv, "", ctsimOptions, NULL); + if (c == -1) + break; + + switch (c) { + case O_VERSION: + std::cout << rcsindent << std::endl; #ifdef CTSIMVERSION - std::cout << "Version: CTSIMVERSION" << std::endl; + std::cout << "Version: CTSIMVERSION" << std::endl; #elif defined(VERSION) - std::cout << "Version: VERSION" << std::endl; + std::cout << "Version: VERSION" << std::endl; #endif - exit(0); - case O_HELP: - case '?': - usage (argv[0]); - exit (0); - default: - usage (argv[0]); - exit (1); - } + exit(0); + case O_HELP: + case '?': + usage (argv[0]); + exit (0); + default: + usage (argv[0]); + exit (1); } - - m_docManager = new wxDocManager; - - new wxDocTemplate (m_docManager, "ImageFile", "*.if", "", "if", "ImageFile doc", "ImageFile View", CLASSINFO(ImageFileDocument), CLASSINFO(ImageFileView)); - - new wxDocTemplate (m_docManager, "ProjectionFile", "*.pj", "", "pj", "ProjectionFile doc", "ProjectionFile View", CLASSINFO(ProjectionFileDocument), CLASSINFO(ProjectionFileView)); - - new wxDocTemplate (m_docManager, "PhantomFile", "*.phm", "", "phm", "Phantom doc", "Phantom View", CLASSINFO(PhantomDocument), CLASSINFO(PhantomView)); - - new wxDocTemplate (m_docManager, "PlotFile", "*.plt", "", "plt", "Plot doc", "Plot View", CLASSINFO(PlotFileDocument), CLASSINFO(PlotFileView)); - - //// Create the main frame window - m_pFrame = new MainFrame(m_docManager, (wxFrame *) NULL, -1, "CTSim", wxPoint(0, 0), wxSize(500, 400), wxDEFAULT_FRAME_STYLE); - - SetTopWindow (m_pFrame); - m_pFrame->Centre(wxBOTH); - - m_pFrame->Show(true); - - for (int i = optind + 1; i <= argc; i++) { - wxString filename = argv [i - 1]; - m_docManager->CreateDocument (filename, wxDOC_SILENT); - } - - return true; + } + + m_docManager = new wxDocManager; + + new wxDocTemplate (m_docManager, "ImageFile", "*.if", "", "if", "ImageFile doc", "ImageFile View", CLASSINFO(ImageFileDocument), CLASSINFO(ImageFileView)); + + new wxDocTemplate (m_docManager, "ProjectionFile", "*.pj", "", "pj", "ProjectionFile doc", "ProjectionFile View", CLASSINFO(ProjectionFileDocument), CLASSINFO(ProjectionFileView)); + + new wxDocTemplate (m_docManager, "PhantomFile", "*.phm", "", "phm", "Phantom doc", "Phantom View", CLASSINFO(PhantomDocument), CLASSINFO(PhantomView)); + + new wxDocTemplate (m_docManager, "PlotFile", "*.plt", "", "plt", "Plot doc", "Plot View", CLASSINFO(PlotFileDocument), CLASSINFO(PlotFileView)); + + //// Create the main frame window + m_pFrame = new MainFrame(m_docManager, (wxFrame *) NULL, -1, "CTSim", wxPoint(0, 0), wxSize(500, 400), wxDEFAULT_FRAME_STYLE); + + SetTopWindow (m_pFrame); + m_pFrame->Centre(wxBOTH); + + m_pFrame->Show(true); + + for (int i = optind + 1; i <= argc; i++) { + wxString filename = argv [i - 1]; + m_docManager->CreateDocument (filename, wxDOC_SILENT); + } + + return true; } void CTSimApp::usage(const char* program) { - std::cout << "usage: " << fileBasename(program) << " [files-to-open...] [OPTIONS]\n"; - std::cout << "Computed Tomography Simulator (Graphical Shell)\n"; - std::cout << "\n"; - std::cout << " --version Display version\n"; - std::cout << " --help Display this help message\n"; + std::cout << "usage: " << fileBasename(program) << " [files-to-open...] [OPTIONS]\n"; + std::cout << "Computed Tomography Simulator (Graphical Shell)\n"; + std::cout << "\n"; + std::cout << " --version Display version\n"; + std::cout << " --help Display this help message\n"; } int CTSimApp::OnExit() { - delete m_docManager; + delete m_docManager; #ifdef HAVE_DMALLOC - dmalloc_shutdown(); + dmalloc_shutdown(); #endif - return 0; + return 0; } wxString CTSimApp::getUntitledFilename() { static int untitledNumber = 1; - + wxString filename ("Untitled"); filename << untitledNumber++; - + return (filename); } @@ -183,137 +183,159 @@ CTSimApp::getUntitledFilename() IMPLEMENT_CLASS(MainFrame, wxDocParentFrame) BEGIN_EVENT_TABLE(MainFrame, wxDocParentFrame) - EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout) - EVT_MENU(MAINMENU_HELP_CONTENTS, MainFrame::OnHelpContents) - EVT_MENU(MAINMENU_FILE_CREATE_PHANTOM, MainFrame::OnCreatePhantom) - EVT_MENU(MAINMENU_FILE_CREATE_FILTER, MainFrame::OnCreateFilter) - EVT_MENU(MAINMENU_FILE_EXIT, MainFrame::OnExit) - EVT_MENU(MAINMENU_WINDOW_BASE, MainFrame::OnWindowMenu0) - EVT_MENU(MAINMENU_WINDOW_BASE+1, MainFrame::OnWindowMenu1) - EVT_MENU(MAINMENU_WINDOW_BASE+2, MainFrame::OnWindowMenu2) - EVT_MENU(MAINMENU_WINDOW_BASE+3, MainFrame::OnWindowMenu3) - EVT_MENU(MAINMENU_WINDOW_BASE+4, MainFrame::OnWindowMenu4) - EVT_MENU(MAINMENU_WINDOW_BASE+5, MainFrame::OnWindowMenu5) - EVT_MENU(MAINMENU_WINDOW_BASE+6, MainFrame::OnWindowMenu6) - EVT_MENU(MAINMENU_WINDOW_BASE+7, MainFrame::OnWindowMenu7) - EVT_MENU(MAINMENU_WINDOW_BASE+8, MainFrame::OnWindowMenu8) - EVT_MENU(MAINMENU_WINDOW_BASE+9, MainFrame::OnWindowMenu9) - EVT_MENU(MAINMENU_WINDOW_BASE+10, MainFrame::OnWindowMenu10) - EVT_MENU(MAINMENU_WINDOW_BASE+11, MainFrame::OnWindowMenu11) - EVT_MENU(MAINMENU_WINDOW_BASE+12, MainFrame::OnWindowMenu12) - EVT_MENU(MAINMENU_WINDOW_BASE+13, MainFrame::OnWindowMenu13) - EVT_MENU(MAINMENU_WINDOW_BASE+14, MainFrame::OnWindowMenu14) - EVT_MENU(MAINMENU_WINDOW_BASE+15, MainFrame::OnWindowMenu15) - EVT_MENU(MAINMENU_WINDOW_BASE+16, MainFrame::OnWindowMenu16) - EVT_MENU(MAINMENU_WINDOW_BASE+17, MainFrame::OnWindowMenu17) - EVT_MENU(MAINMENU_WINDOW_BASE+18, MainFrame::OnWindowMenu18) - EVT_MENU(MAINMENU_WINDOW_BASE+19, MainFrame::OnWindowMenu19) - EVT_UPDATE_UI_RANGE(MAINMENU_WINDOW_BASE, MAINMENU_WINDOW_BASE+20, MainFrame::OnUpdateUI) +EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout) +EVT_MENU(MAINMENU_HELP_CONTENTS, MainFrame::OnHelpContents) +EVT_MENU(MAINMENU_FILE_CREATE_PHANTOM, MainFrame::OnCreatePhantom) +EVT_MENU(MAINMENU_FILE_CREATE_FILTER, MainFrame::OnCreateFilter) +EVT_MENU(MAINMENU_FILE_EXIT, MainFrame::OnExit) +EVT_MENU(MAINMENU_WINDOW_BASE, MainFrame::OnWindowMenu0) +EVT_MENU(MAINMENU_WINDOW_BASE+1, MainFrame::OnWindowMenu1) +EVT_MENU(MAINMENU_WINDOW_BASE+2, MainFrame::OnWindowMenu2) +EVT_MENU(MAINMENU_WINDOW_BASE+3, MainFrame::OnWindowMenu3) +EVT_MENU(MAINMENU_WINDOW_BASE+4, MainFrame::OnWindowMenu4) +EVT_MENU(MAINMENU_WINDOW_BASE+5, MainFrame::OnWindowMenu5) +EVT_MENU(MAINMENU_WINDOW_BASE+6, MainFrame::OnWindowMenu6) +EVT_MENU(MAINMENU_WINDOW_BASE+7, MainFrame::OnWindowMenu7) +EVT_MENU(MAINMENU_WINDOW_BASE+8, MainFrame::OnWindowMenu8) +EVT_MENU(MAINMENU_WINDOW_BASE+9, MainFrame::OnWindowMenu9) +EVT_MENU(MAINMENU_WINDOW_BASE+10, MainFrame::OnWindowMenu10) +EVT_MENU(MAINMENU_WINDOW_BASE+11, MainFrame::OnWindowMenu11) +EVT_MENU(MAINMENU_WINDOW_BASE+12, MainFrame::OnWindowMenu12) +EVT_MENU(MAINMENU_WINDOW_BASE+13, MainFrame::OnWindowMenu13) +EVT_MENU(MAINMENU_WINDOW_BASE+14, MainFrame::OnWindowMenu14) +EVT_MENU(MAINMENU_WINDOW_BASE+15, MainFrame::OnWindowMenu15) +EVT_MENU(MAINMENU_WINDOW_BASE+16, MainFrame::OnWindowMenu16) +EVT_MENU(MAINMENU_WINDOW_BASE+17, MainFrame::OnWindowMenu17) +EVT_MENU(MAINMENU_WINDOW_BASE+18, MainFrame::OnWindowMenu18) +EVT_MENU(MAINMENU_WINDOW_BASE+19, MainFrame::OnWindowMenu19) +EVT_UPDATE_UI_RANGE(MAINMENU_WINDOW_BASE, MAINMENU_WINDOW_BASE+20, MainFrame::OnUpdateUI) END_EVENT_TABLE() MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type) - : wxDocParentFrame(manager, frame, id, title, pos, size, type), m_pLog(NULL) +: wxDocParentFrame(manager, frame, id, title, pos, size, type), m_pLog(NULL) { - m_pLog = new wxTextCtrl (this, -1, "Log Window\n", wxPoint(0, 250), wxSize(100,50), wxTE_MULTILINE | wxTE_READONLY); - wxLog::SetActiveTarget(new wxLogTextCtrl(m_pLog)); - CreateStatusBar(); - SetStatusText ("Welcome to CTSim"); - - //// Make a menubar - wxMenu *file_menu = new wxMenu; - - file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom..."); - file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter..."); - file_menu->Append(wxID_OPEN, "&Open..."); - - file_menu->AppendSeparator(); - file_menu->Append(MAINMENU_FILE_EXIT, "E&xit"); - - // history of files visited - m_docManager->FileHistoryUseMenu(file_menu); - - m_pWindowMenu = new wxMenu; - m_pWindowMenu->UpdateUI (this); - - wxMenu* help_menu = new wxMenu; - help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents"); - help_menu->AppendSeparator(); - help_menu->Append(MAINMENU_HELP_ABOUT, "&About"); - - wxMenuBar* menu_bar = new wxMenuBar; - - menu_bar->Append(file_menu, "&File"); - menu_bar->Append(m_pWindowMenu, "&Window"); - menu_bar->Append(help_menu, "&Help"); - - SetMenuBar(menu_bar); - - for (int i = 0; i < MAX_WINDOW_MENUITEMS; i++) { - m_apWindowMenuItems[i] = new wxMenuItem (m_pWindowMenu, MAINMENU_WINDOW_BASE+i, wxString("")); - m_pWindowMenu->Append (m_apWindowMenuItems[i]); - m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false); - } + m_pLog = new wxTextCtrl (this, -1, "Log Window\n", wxPoint(0, 250), wxSize(100,50), wxTE_MULTILINE | wxTE_READONLY); + wxLog::SetActiveTarget(new wxLogTextCtrl(m_pLog)); + CreateStatusBar(); + SetStatusText ("Welcome to CTSim"); + + //// Make a menubar + wxMenu *file_menu = new wxMenu; + + file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom..."); + file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter..."); + file_menu->Append(wxID_OPEN, "&Open..."); + + file_menu->AppendSeparator(); + file_menu->Append(MAINMENU_FILE_EXIT, "E&xit"); + + // history of files visited + m_docManager->FileHistoryUseMenu(file_menu); + + m_pWindowMenu = new wxMenu; + m_pWindowMenu->UpdateUI (this); + + wxMenu* help_menu = new wxMenu; + help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents"); + help_menu->AppendSeparator(); + help_menu->Append(MAINMENU_HELP_ABOUT, "&About"); + + wxMenuBar* menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, "&File"); + menu_bar->Append(m_pWindowMenu, "&Window"); + menu_bar->Append(help_menu, "&Help"); + + SetMenuBar(menu_bar); + + for (int i = 0; i < MAX_WINDOW_MENUITEMS; i++) { + m_apWindowMenuItems[i] = new wxMenuItem (m_pWindowMenu, MAINMENU_WINDOW_BASE+i, wxString("")); + m_pWindowMenu->Append (m_apWindowMenuItems[i]); + m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false); + } + + m_iDefaultPhantomID = Phantom::PHM_HERMAN; + m_iDefaultFilterID = SignalFilter::FILTER_BANDLIMIT; + m_iDefaultFilterDomainID = SignalFilter::DOMAIN_FREQUENCY; + m_iDefaultFilterXSize = 256; + m_iDefaultFilterYSize = 256; + m_dDefaultFilterParam = 1.; + m_dDefaultFilterBandwidth = 1.; + m_dDefaultFilterInputScale = 1.; + m_dDefaultFilterOutputScale = 1.; + } void MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) { - wxString msg = "CTSim\nThe Open Source Computed Tomography Simulator\n"; + wxString msg = "CTSim\nThe Open Source Computed Tomography Simulator\n"; #ifdef CTSIMVERSION - msg += "Version "; - msg += CTSIMVERSION; - msg += "\n\n"; + msg += "Version "; + msg += CTSIMVERSION; + msg += "\n\n"; #elif defined(VERSION) - msg << "Version: " << VERSION << "\n\n"; + msg << "Version: " << VERSION << "\n\n"; #endif - msg += "Author: Kevin Rosenberg \nUsage: ctsim [files-to-open..] [--help]"; - - wxMessageBox(msg, "About CTSim", wxOK | wxICON_INFORMATION, this); + msg += "Author: Kevin Rosenberg \nUsage: ctsim [files-to-open..] [--help]"; + + wxMessageBox(msg, "About CTSim", wxOK | wxICON_INFORMATION, this); } - + void MainFrame::OnCreatePhantom(wxCommandEvent& WXUNUSED(event)) { - DialogGetPhantom dialogPhantom (this, Phantom::PHM_HERMAN); - int dialogReturn = dialogPhantom.ShowModal(); - if (dialogReturn == wxID_OK) { - wxString selection (dialogPhantom.getPhantom()); - *theApp->getLog() << "Selected phantom " << selection.c_str() << "\n"; - wxString filename = selection + ".phm"; - theApp->getDocManager()->CreateDocument(filename, wxDOC_SILENT); - } - + DialogGetPhantom dialogPhantom (this, m_iDefaultPhantomID); + int dialogReturn = dialogPhantom.ShowModal(); + if (dialogReturn == wxID_OK) { + wxString selection (dialogPhantom.getPhantom()); + *theApp->getLog() << "Selected phantom " << selection.c_str() << "\n"; + wxString filename = selection + ".phm"; + m_iDefaultPhantomID = Phantom::convertNameToPhantomID (selection.c_str()); + theApp->getDocManager()->CreateDocument(filename, wxDOC_SILENT); + } + } void MainFrame::OnCreateFilter (wxCommandEvent& WXUNUSED(event)) { - DialogGetFilterParameters dialogFilter (this, 256, 256, SignalFilter::FILTER_BANDLIMIT, 1., 10., SignalFilter::DOMAIN_SPATIAL); - int dialogReturn = dialogFilter.ShowModal(); - if (dialogReturn == wxID_OK) { - wxString strFilter (dialogFilter.getFilterName()); - wxString strDomain (dialogFilter.getDomainName()); - unsigned int nx = dialogFilter.getXSize(); - unsigned int ny = dialogFilter.getYSize(); - double dBandwidth = dialogFilter.getBandwidth(); - double dFilterParam= dialogFilter.getFilterParam(); - *theApp->getLog() << "Selected filter " << strFilter.c_str() << ", domain " << strDomain.c_str() << ", filterParam " << dFilterParam << ", bandwidth " << dBandwidth << "\n"; - wxString filename = "untitled.if"; - ImageFileDocument* pFilterDoc = dynamic_cast(theApp->getDocManager()->CreateDocument ("untitled.if", wxDOC_SILENT)); - if (! pFilterDoc) { - sys_error (ERR_SEVERE, "Unable to create filter image"); - return; - } - ImageFile& rIF = pFilterDoc->getImageFile(); - rIF.setArraySize (nx, ny); - rIF.filterResponse (strDomain.c_str(), dBandwidth, strFilter.c_str(), dFilterParam); - if (theApp->getSetModifyNewDocs()) - pFilterDoc->Modify (true); - pFilterDoc->UpdateAllViews(); - pFilterDoc->GetFirstView()->OnUpdate (NULL, NULL); + DialogGetFilterParameters dialogFilter (this, m_iDefaultFilterXSize, m_iDefaultFilterYSize, m_iDefaultFilterID, m_dDefaultFilterParam, m_dDefaultFilterBandwidth, m_iDefaultFilterDomainID, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale); + int dialogReturn = dialogFilter.ShowModal(); + if (dialogReturn == wxID_OK) { + wxString strFilter (dialogFilter.getFilterName()); + wxString strDomain (dialogFilter.getDomainName()); + m_iDefaultFilterID = SignalFilter::convertFilterNameToID (strFilter.c_str()); + m_iDefaultFilterDomainID = SignalFilter::convertDomainNameToID (strDomain.c_str()); + m_iDefaultFilterXSize = dialogFilter.getXSize(); + m_iDefaultFilterYSize = dialogFilter.getYSize(); + m_dDefaultFilterBandwidth = dialogFilter.getBandwidth(); + m_dDefaultFilterParam= dialogFilter.getFilterParam(); + m_dDefaultFilterInputScale = dialogFilter.getInputScale(); + m_dDefaultFilterOutputScale = dialogFilter.getOutputScale(); + std::ostringstream os; + os << "Generate Filter=" << strFilter.c_str() + << ", size=(" << static_cast(m_iDefaultFilterXSize) << "," << static_cast(m_iDefaultFilterYSize) + << "), domain=" << strDomain.c_str() << ", filterParam=" << m_dDefaultFilterParam << ", bandwidth=" << m_dDefaultFilterBandwidth + << ", inputScale=" << m_dDefaultFilterInputScale << ", outputScale=" << m_dDefaultFilterOutputScale; + *theApp->getLog() << os.str().c_str() << "\n"; + wxString filename = "untitled.if"; + ImageFileDocument* pFilterDoc = dynamic_cast(theApp->getDocManager()->CreateDocument ("untitled.if", wxDOC_SILENT)); + if (! pFilterDoc) { + sys_error (ERR_SEVERE, "Unable to create filter image"); + return; } + ImageFile& rIF = pFilterDoc->getImageFile(); + rIF.setArraySize (m_iDefaultFilterXSize, m_iDefaultFilterYSize); + rIF.filterResponse (strDomain.c_str(), m_dDefaultFilterBandwidth, strFilter.c_str(), m_dDefaultFilterParam, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale); + rIF.labelAdd (os.str().c_str()); + if (theApp->getSetModifyNewDocs()) + pFilterDoc->Modify (true); + pFilterDoc->UpdateAllViews(); + pFilterDoc->GetFirstView()->OnUpdate (NULL, NULL); + } } void @@ -337,13 +359,13 @@ CTSimApp::getCompatibleImages (const ImageFileDocument* pIFDoc, std::vector(m_apWindowMenuItems[i])->SetName (wxString("")); m_apWindowMenuData[i] = NULL; } - + } void diff --git a/src/ctsim.h b/src/ctsim.h index 2055227..aa349c1 100644 --- a/src/ctsim.h +++ b/src/ctsim.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ctsim.h,v 1.16 2001/01/01 10:14:34 kevin Exp $ +** $Id: ctsim.h,v 1.17 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 @@ -53,6 +53,16 @@ private: enum { MAX_WINDOW_MENUITEMS = 20 }; wxMenuItem* m_apWindowMenuItems[MAX_WINDOW_MENUITEMS]; wxDocument* m_apWindowMenuData[MAX_WINDOW_MENUITEMS]; + + int m_iDefaultPhantomID; + int m_iDefaultFilterID; + int m_iDefaultFilterDomainID; + unsigned int m_iDefaultFilterXSize; + unsigned int m_iDefaultFilterYSize; + double m_dDefaultFilterParam; + double m_dDefaultFilterBandwidth; + double m_dDefaultFilterInputScale; + double m_dDefaultFilterOutputScale; public: MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type); @@ -137,11 +147,12 @@ enum { MAINMENU_HELP_CONTENTS, MAINMENU_FILE_CREATE_PHANTOM, MAINMENU_FILE_CREATE_FILTER, - MAINMENU_FILE_EXIT, + MAINMENU_FILE_EXIT, IFMENU_FILE_PROPERTIES, PJMENU_FILE_PROPERTIES, PHMMENU_FILE_PROPERTIES, PJMENU_PROCESS_RECONSTRUCT, + IFMENU_FILE_EXPORT, IFMENU_PLOT_ROW, IFMENU_PLOT_COL, IFMENU_VIEW_SCALE_AUTO, @@ -154,12 +165,19 @@ enum { IFMENU_PROCESS_SQUARE, IFMENU_PROCESS_LOG, IFMENU_PROCESS_EXP, + IFMENU_PROCESS_MULTIPLY, + IFMENU_PROCESS_SUBTRACT, + IFMENU_PROCESS_SCALESIZE, + IFMENU_PROCESS_DIVIDE, + IFMENU_PROCESS_ADD, IFMENU_PROCESS_FOURIER, IFMENU_PROCESS_INVERSE_FOURIER, IFMENU_PROCESS_FFT, IFMENU_PROCESS_IFFT, IFMENU_PROCESS_MAGNITUDE, IFMENU_PROCESS_PHASE, + IFMENU_PROCESS_SHUFFLENATURALTOFOURIERORDER, + IFMENU_PROCESS_SHUFFLEFOURIERTONATURALORDER, PHMMENU_PROCESS_RASTERIZE, PHMMENU_PROCESS_PROJECTIONS, PLOTMENU_VIEW_SCALE_MINMAX, diff --git a/src/dialogs.cpp b/src/dialogs.cpp index 3e2d8fb..4802162 100644 --- a/src/dialogs.cpp +++ b/src/dialogs.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: dialogs.cpp,v 1.22 2001/01/01 10:14:34 kevin Exp $ +** $Id: dialogs.cpp,v 1.23 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 @@ -821,7 +821,7 @@ DialogGetReconstructionParameters::getFilterGenerationName (void) ///////////////////////////////////////////////////////////////////// -DialogGetFilterParameters::DialogGetFilterParameters (wxFrame* pParent, int iDefaultXSize, int iDefaultYSize, int iDefaultFilterID, double dDefaultFilterParam, double dDefaultBandwidth, int iDefaultDomainID) +DialogGetFilterParameters::DialogGetFilterParameters (wxFrame* pParent, int iDefaultXSize, int iDefaultYSize, int iDefaultFilterID, double dDefaultFilterParam, double dDefaultBandwidth, int iDefaultDomainID, double dDefaultInputScale, double dDefaultOutputScale) : wxDialog (pParent, -1, "Set Filter Parameters", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxCAPTION) { wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL); @@ -842,6 +842,12 @@ DialogGetFilterParameters::DialogGetFilterParameters (wxFrame* pParent, int iDef std::ostringstream osBandwidth; osBandwidth << dDefaultBandwidth; m_pTextCtrlBandwidth = new wxTextCtrl (this, -1, osBandwidth.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + std::ostringstream osInputScale; + osInputScale << dDefaultInputScale; + m_pTextCtrlInputScale = new wxTextCtrl (this, -1, osInputScale.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + std::ostringstream osOutputScale; + osOutputScale << dDefaultOutputScale; + m_pTextCtrlOutputScale = new wxTextCtrl (this, -1, osOutputScale.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); wxFlexGridSizer* pGridSizer = new wxFlexGridSizer (2); pGridSizer->Add (new wxStaticText (this, -1, "Filter"), 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5); @@ -862,6 +868,10 @@ DialogGetFilterParameters::DialogGetFilterParameters (wxFrame* pParent, int iDef pGridSizer->Add (m_pTextCtrlFilterParam, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (new wxStaticText (this, -1, "Bandwidth"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); pGridSizer->Add (m_pTextCtrlBandwidth, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (new wxStaticText (this, -1, "Axis (input) Scale"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlInputScale, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (new wxStaticText (this, -1, "Filter Output Scale"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlOutputScale, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); pTopSizer->Add (pGridSizer, 1, wxALL, 3); @@ -931,6 +941,28 @@ DialogGetFilterParameters::getFilterParam (void) return (m_dDefaultFilterParam); } +double +DialogGetFilterParameters::getInputScale (void) +{ + wxString strCtrl = m_pTextCtrlInputScale->GetValue(); + double dValue; + if (strCtrl.ToDouble (&dValue)) + return dValue; + else + return (m_dDefaultInputScale); +} + +double +DialogGetFilterParameters::getOutputScale (void) +{ + wxString strCtrl = m_pTextCtrlOutputScale->GetValue(); + double dValue; + if (strCtrl.ToDouble (&dValue)) + return dValue; + else + return (m_dDefaultOutputScale); +} + const char* DialogGetFilterParameters::getFilterName (void) { @@ -943,3 +975,117 @@ DialogGetFilterParameters::getDomainName (void) return m_pListBoxDomain->getSelectionStringValue(); } + +/////////////////////////////////////////////////////////////////////// +// CLASS IMPLEMENTATION +// DialogExportParameters +/////////////////////////////////////////////////////////////////////// + +DialogExportParameters::DialogExportParameters (wxFrame* pParent, int iDefaultFormatID) +: wxDialog (pParent, -1, "Select ExportParameters", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxCAPTION) +{ + wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL); + + pTopSizer->Add (new wxStaticText (this, -1, "Select Export Format"), 0, wxALIGN_CENTER | wxALL, 5); + + pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxALL, 5); + + m_pListBoxFormat = new StringValueAndTitleListBox (this, ImageFile::getFormatCount(), ImageFile::getFormatTitleArray(), ImageFile::getFormatNameArray()); + m_pListBoxFormat->SetSelection (iDefaultFormatID); + pTopSizer->Add (m_pListBoxFormat, 0, wxALL | wxALIGN_CENTER | wxEXPAND); + + pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); + + wxBoxSizer* pButtonSizer = new wxBoxSizer (wxHORIZONTAL); + wxButton* pButtonOk = new wxButton (this, wxID_OK, "Okay"); + wxButton* pButtonCancel = new wxButton (this, wxID_CANCEL, "Cancel"); + pButtonSizer->Add (pButtonOk, 0, wxEXPAND | wxALL, 10); + pButtonSizer->Add (pButtonCancel, 0, wxEXPAND | wxALL, 10); + + pTopSizer->Add (pButtonSizer, 0, wxALIGN_CENTER); + + SetAutoLayout (true); + SetSizer (pTopSizer); + pTopSizer->Fit (this); + pTopSizer->SetSizeHints (this); +} + +const char* +DialogExportParameters::getFormatName(void) +{ + return m_pListBoxFormat->getSelectionStringValue(); +} + + +///////////////////////////////////////////////////////////////////// +// CLASS DiaglogGetXYSize Implementation +///////////////////////////////////////////////////////////////////// + +DialogGetXYSize::DialogGetXYSize (wxFrame* pParent, const char* const pszTitle, int iDefaultXSize, int iDefaultYSize) +: wxDialog (pParent, -1, pszTitle, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxCAPTION) +{ + m_iDefaultXSize = iDefaultXSize; + m_iDefaultYSize = iDefaultYSize; + + wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL); + + pTopSizer->Add (new wxStaticText (this, -1, pszTitle), 0, wxALIGN_CENTER | wxTOP | wxLEFT | wxRIGHT, 5); + + pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); + + std::ostringstream os; + os << iDefaultXSize; + m_pTextCtrlXSize = new wxTextCtrl (this, -1, os.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + std::ostringstream osYSize; + osYSize << iDefaultYSize; + m_pTextCtrlYSize = new wxTextCtrl (this, -1, osYSize.str().c_str(), wxDefaultPosition, wxSize(100, 25), 0); + + wxFlexGridSizer *pGridSizer = new wxFlexGridSizer (2); + pGridSizer->Add (new wxStaticText (this, -1, "X Size"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlXSize, 0, wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (new wxStaticText (this, -1, "Y Size"), 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); + pGridSizer->Add (m_pTextCtrlYSize, 0, wxALIGN_CENTER_VERTICAL); + pTopSizer->Add (pGridSizer, 1, wxALL, 10); + + pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5); + + wxBoxSizer* pButtonSizer = new wxBoxSizer (wxHORIZONTAL); + wxButton* pButtonOk = new wxButton (this, wxID_OK, "Okay"); + wxButton* pButtonCancel = new wxButton (this, wxID_CANCEL, "Cancel"); + pButtonSizer->Add (pButtonOk, 0, wxEXPAND | wxALL, 10); + pButtonSizer->Add (pButtonCancel, 0, wxEXPAND | wxALL, 10); + + pTopSizer->Add (pButtonSizer, 0, wxALIGN_CENTER); + + SetAutoLayout (true); + SetSizer (pTopSizer); + pTopSizer->Fit (this); + pTopSizer->SetSizeHints (this); +} + +DialogGetXYSize::~DialogGetXYSize (void) +{ +} + +unsigned int +DialogGetXYSize::getXSize (void) +{ + wxString strCtrl = m_pTextCtrlXSize->GetValue(); + long lValue; + if (strCtrl.ToLong (&lValue)) + return lValue; + else + return (m_iDefaultXSize); +} + +unsigned int +DialogGetXYSize::getYSize (void) +{ + wxString strCtrl = m_pTextCtrlYSize->GetValue(); + long lValue; + if (strCtrl.ToLong (&lValue)) + return lValue; + else + return (m_iDefaultYSize); +} + diff --git a/src/dialogs.h b/src/dialogs.h index 3546021..baf9a2f 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: dialogs.h,v 1.17 2001/01/01 10:14:34 kevin Exp $ +** $Id: dialogs.h,v 1.18 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 @@ -87,7 +87,6 @@ class DialogGetComparisonImage : public wxDialog }; - class ImageFile; class DialogGetMinMax : public wxDialog { @@ -211,7 +210,7 @@ class DialogGetReconstructionParameters : public wxDialog class DialogGetFilterParameters : public wxDialog { public: - DialogGetFilterParameters (wxFrame* pParent, int iDefaultXSize = 0, int iDefaultYSize = 0, int iDefaultFilterID = SignalFilter::FILTER_BANDLIMIT, double dDefaultFilterParam = 1., double dDefaultBandwidth = 1., int iDefaultDomain = SignalFilter::DOMAIN_SPATIAL); + DialogGetFilterParameters (wxFrame* pParent, int iDefaultXSize = 0, int iDefaultYSize = 0, int iDefaultFilterID = SignalFilter::FILTER_BANDLIMIT, double dDefaultFilterParam = 1., double dDefaultBandwidth = 1., int iDefaultDomain = SignalFilter::DOMAIN_SPATIAL, double dDefaultInputScale = 1., double dDefaultOutputScale = 1.); virtual ~DialogGetFilterParameters (); unsigned int getXSize(); @@ -219,12 +218,16 @@ class DialogGetFilterParameters : public wxDialog const char* getFilterName(); const char* getDomainName(); double getFilterParam(); + double getInputScale(); + double getOutputScale(); double getBandwidth(); private: wxTextCtrl* m_pTextCtrlXSize; wxTextCtrl* m_pTextCtrlYSize; wxTextCtrl* m_pTextCtrlFilterParam; + wxTextCtrl* m_pTextCtrlOutputScale; + wxTextCtrl* m_pTextCtrlInputScale; wxTextCtrl* m_pTextCtrlBandwidth; StringValueAndTitleListBox* m_pListBoxFilter; @@ -234,9 +237,23 @@ class DialogGetFilterParameters : public wxDialog int m_iDefaultYSize; double m_dDefaultFilterParam; double m_dDefaultBandwidth; + double m_dDefaultOutputScale; + double m_dDefaultInputScale; int m_iDefaultDomain; }; +class DialogExportParameters : public wxDialog +{ + public: + DialogExportParameters (wxFrame* pParent, int iDefaultFormatID); + virtual ~DialogExportParameters () {} + + const char* getFormatName(); + + private: + StringValueAndTitleListBox* m_pListBoxFormat; +}; + class DialogAutoScaleParameters : public wxDialog { public: @@ -255,6 +272,24 @@ class DialogAutoScaleParameters : public wxDialog wxTextCtrl* m_pTextCtrlStdDevFactor; wxListBox* m_pListBoxCenter; }; + +class DialogGetXYSize : public wxDialog +{ + public: + DialogGetXYSize (wxFrame* pParent, const char* const pszTitle, int iDefaultXSize = 1, int iDefaultYSize = 1); + virtual ~DialogGetXYSize (); + + unsigned int getXSize (); + unsigned int getYSize (); + + private: + wxTextCtrl* m_pTextCtrlXSize; + wxTextCtrl* m_pTextCtrlYSize; + + unsigned int m_iDefaultXSize; + unsigned int m_iDefaultYSize; +}; + #endif diff --git a/src/docs.cpp b/src/docs.cpp index bab1d13..69b5954 100644 --- a/src/docs.cpp +++ b/src/docs.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: docs.cpp,v 1.9 2000/12/29 15:45:06 kevin Exp $ +** $Id: docs.cpp,v 1.10 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 @@ -180,6 +180,17 @@ bool PhantomDocument::OnOpenDocument(const wxString& filename) return true; } +bool PhantomDocument::OnSaveDocument(const wxString& filename) +{ + if (! m_phantom.fileWrite (filename.c_str())) { + *theApp->getLog() << "Unable to write phantom file " << filename << "\n"; + return false; + } + *theApp->getLog() << "Wrote phantom file " << filename << "\n"; + Modify(false); + return true; +} + bool PhantomDocument::OnCloseDocument () { bool bReturn = wxDocument::OnCloseDocument(); @@ -229,6 +240,7 @@ bool PlotFileDocument::OnOpenDocument(const wxString& filename) } Modify (false); UpdateAllViews(); + GetFirstView()->OnUpdate (NULL, NULL); return true; } diff --git a/src/docs.h b/src/docs.h index 3729ce4..c1da82a 100644 --- a/src/docs.h +++ b/src/docs.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: docs.h,v 1.9 2000/12/27 03:16:02 kevin Exp $ +** $Id: docs.h,v 1.10 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 @@ -117,6 +117,7 @@ public: { return m_phantom; } virtual bool OnOpenDocument (const wxString& filename); + virtual bool OnSaveDocument (const wxString& filename); virtual bool OnCloseDocument (); virtual bool IsModified () const; virtual void Modify (bool mod); diff --git a/src/views.cpp b/src/views.cpp index 93d49b3..3ec3b6b 100644 --- a/src/views.cpp +++ b/src/views.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: views.cpp,v 1.43 2001/01/01 10:14:34 kevin Exp $ +** $Id: views.cpp,v 1.44 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 @@ -165,7 +165,8 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event) IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView) -BEGIN_EVENT_TABLE(ImageFileView, wxView) +BEGIN_EVENT_TABLE(ImageFileView, wxView) +EVT_MENU(IFMENU_FILE_EXPORT, ImageFileView::OnExport) EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties) EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax) EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto) @@ -177,8 +178,15 @@ EVT_MENU(IFMENU_PROCESS_SQUARE, ImageFileView::OnSquare) EVT_MENU(IFMENU_PROCESS_SQRT, ImageFileView::OnSquareRoot) EVT_MENU(IFMENU_PROCESS_LOG, ImageFileView::OnLog) EVT_MENU(IFMENU_PROCESS_EXP, ImageFileView::OnExp) +EVT_MENU(IFMENU_PROCESS_ADD, ImageFileView::OnAdd) +EVT_MENU(IFMENU_PROCESS_SUBTRACT, ImageFileView::OnSubtract) +EVT_MENU(IFMENU_PROCESS_MULTIPLY, ImageFileView::OnMultiply) +EVT_MENU(IFMENU_PROCESS_DIVIDE, ImageFileView::OnDivide) EVT_MENU(IFMENU_PROCESS_FOURIER, ImageFileView::OnFourier) +EVT_MENU(IFMENU_PROCESS_SCALESIZE, ImageFileView::OnScaleSize) EVT_MENU(IFMENU_PROCESS_INVERSE_FOURIER, ImageFileView::OnInverseFourier) +EVT_MENU(IFMENU_PROCESS_SHUFFLEFOURIERTONATURALORDER, ImageFileView::OnShuffleFourierToNaturalOrder) +EVT_MENU(IFMENU_PROCESS_SHUFFLENATURALTOFOURIERORDER, ImageFileView::OnShuffleNaturalToFourierOrder) #ifdef HAVE_FFTW EVT_MENU(IFMENU_PROCESS_FFT, ImageFileView::OnFFT) EVT_MENU(IFMENU_PROCESS_IFFT, ImageFileView::OnIFFT) @@ -191,7 +199,8 @@ END_EVENT_TABLE() ImageFileView::ImageFileView(void) : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false) -{ +{ + m_iDefaultExportFormatID = ImageFile::FORMAT_PNG; } ImageFileView::~ImageFileView(void) @@ -221,6 +230,10 @@ ImageFileView::OnProperties (wxCommandEvent& event) rIF.statistics (rIF.getImaginaryArray(), min, max, mean, mode, median, stddev); os << "\nImaginary: min: "< 0) { + os << "\n"; + rIF.printLabelsBrief (os); + } *theApp->getLog() << os.str().c_str(); wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Imagefile Properties", wxOK | wxICON_INFORMATION); dialogMsg.ShowModal(); @@ -292,7 +305,7 @@ ImageFileView::OnCompare (wxCommandEvent& event) rIF.statistics (min, max, mean, mode, median, stddev); os << rIF.getFilename() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n"; rCompareIF.statistics (min, max, mean, mode, median, stddev); - os << pCompareDoc->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n"; + os << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n"; os << "\n"; double d, r, e; rIF.comparativeStatistics (rCompareIF, d, r, e); @@ -327,6 +340,7 @@ ImageFileView::OnInvertValues (wxCommandEvent& event) { ImageFile& rIF = GetDocument()->getImageFile(); rIF.invertPixelValues (rIF); + rIF.labelAdd ("Invert Pixel Values"); if (theApp->getSetModifyNewDocs()) GetDocument()->Modify(TRUE); GetDocument()->UpdateAllViews(this); @@ -337,6 +351,7 @@ ImageFileView::OnSquare (wxCommandEvent& event) { ImageFile& rIF = GetDocument()->getImageFile(); rIF.square (rIF); + rIF.labelAdd ("Square Pixel Values"); if (theApp->getSetModifyNewDocs()) GetDocument()->Modify(TRUE); GetDocument()->UpdateAllViews(this); @@ -347,6 +362,7 @@ ImageFileView::OnSquareRoot (wxCommandEvent& event) { ImageFile& rIF = GetDocument()->getImageFile(); rIF.sqrt (rIF); + rIF.labelAdd ("Square-root Pixel Values"); if (theApp->getSetModifyNewDocs()) GetDocument()->Modify(TRUE); GetDocument()->UpdateAllViews(this); @@ -357,6 +373,7 @@ ImageFileView::OnLog (wxCommandEvent& event) { ImageFile& rIF = GetDocument()->getImageFile(); rIF.log (rIF); + rIF.labelAdd ("Logrithm base-e Pixel Values"); if (theApp->getSetModifyNewDocs()) GetDocument()->Modify(TRUE); GetDocument()->UpdateAllViews(this); @@ -367,24 +384,125 @@ ImageFileView::OnExp (wxCommandEvent& event) { ImageFile& rIF = GetDocument()->getImageFile(); rIF.exp (rIF); + rIF.labelAdd ("Exponent base-e Pixel Values"); if (theApp->getSetModifyNewDocs()) GetDocument()->Modify(TRUE); GetDocument()->UpdateAllViews(this); } void -ImageFileView::OnFourier (wxCommandEvent& event) +ImageFileView::OnAdd (wxCommandEvent& event) { - ImageFile& rIF = GetDocument()->getImageFile(); - wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, m_frame, wxPD_APP_MODAL); - rIF.fourier (rIF); - m_bMinSpecified = false; - m_bMaxSpecified = false; - if (theApp->getSetModifyNewDocs()) - GetDocument()->Modify(TRUE); - GetDocument()->UpdateAllViews(this); + std::vector vecIF; + theApp->getCompatibleImages (GetDocument(), vecIF); + + if (vecIF.size() == 0) { + wxMessageBox ("There are no compatible image files open for comparision", "No comparison images"); + } else { + DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Add", vecIF, false); + + if (dialogGetCompare.ShowModal() == wxID_OK) { + ImageFile& rIF = GetDocument()->getImageFile(); + ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument(); + const ImageFile& rRHSIF = pRHSDoc->getImageFile(); + rIF.addImages (rRHSIF, rIF); + std::ostringstream os; + os << "Add image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and " + << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str(); + rIF.labelAdd (os.str().c_str()); + *theApp->getLog() << os.str().c_str() << "\n"; + if (theApp->getSetModifyNewDocs()) + GetDocument()->Modify(TRUE); + GetDocument()->UpdateAllViews(this); + } + } } +void +ImageFileView::OnSubtract (wxCommandEvent& event) +{ + std::vector vecIF; + theApp->getCompatibleImages (GetDocument(), vecIF); + + if (vecIF.size() == 0) { + wxMessageBox ("There are no compatible image files open for comparision", "No comparison images"); + } else { + DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Subtract", vecIF, false); + + if (dialogGetCompare.ShowModal() == wxID_OK) { + ImageFile& rIF = GetDocument()->getImageFile(); + ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument(); + const ImageFile& rRHSIF = pRHSDoc->getImageFile(); + rIF.subtractImages (rRHSIF, rIF); + std::ostringstream os; + os << "Subtract image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() + << " and " << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str(); + rIF.labelAdd (os.str().c_str()); + *theApp->getLog() << os.str().c_str() << "\n"; + if (theApp->getSetModifyNewDocs()) + GetDocument()->Modify(TRUE); + GetDocument()->UpdateAllViews(this); + } + } +} + +void +ImageFileView::OnMultiply (wxCommandEvent& event) +{ + std::vector vecIF; + theApp->getCompatibleImages (GetDocument(), vecIF); + + if (vecIF.size() == 0) { + wxMessageBox ("There are no compatible image files open for comparision", "No comparison images"); + } else { + DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Multiply", vecIF, false); + + if (dialogGetCompare.ShowModal() == wxID_OK) { + ImageFile& rIF = GetDocument()->getImageFile(); + ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument(); + const ImageFile& rRHSIF = pRHSDoc->getImageFile(); + rIF.multiplyImages (rRHSIF, rIF); + std::ostringstream os; + os << "Multiply image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() + << " and " << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str(); + rIF.labelAdd (os.str().c_str()); + *theApp->getLog() << os.str().c_str() << "\n"; + if (theApp->getSetModifyNewDocs()) + GetDocument()->Modify(TRUE); + GetDocument()->UpdateAllViews(this); + } + } +} + +void +ImageFileView::OnDivide (wxCommandEvent& event) +{ + std::vector vecIF; + theApp->getCompatibleImages (GetDocument(), vecIF); + + if (vecIF.size() == 0) { + wxMessageBox ("There are no compatible image files open for comparision", "No comparison images"); + } else { + DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Divide", vecIF, false); + + if (dialogGetCompare.ShowModal() == wxID_OK) { + ImageFile& rIF = GetDocument()->getImageFile(); + ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument(); + const ImageFile& rRHSIF = pRHSDoc->getImageFile(); + rIF.divideImages (rRHSIF, rIF); + std::ostringstream os; + os << "Divide image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() + << " by " << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str(); + rIF.labelAdd (os.str().c_str()); + *theApp->getLog() << os.str().c_str() << "\n"; + if (theApp->getSetModifyNewDocs()) + GetDocument()->Modify(TRUE); + GetDocument()->UpdateAllViews(this); + } + } +} + + #ifdef HAVE_FFTW void ImageFileView::OnFFT (wxCommandEvent& event) @@ -392,6 +510,7 @@ ImageFileView::OnFFT (wxCommandEvent& event) ImageFile& rIF = GetDocument()->getImageFile(); wxProgressDialog dlgProgress (wxString("FFT"), wxString("FFT Progress"), 1, m_frame, wxPD_APP_MODAL); rIF.fft (rIF); + rIF.labelAdd ("FFT Image"); m_bMinSpecified = false; m_bMaxSpecified = false; if (theApp->getSetModifyNewDocs()) @@ -405,6 +524,7 @@ ImageFileView::OnIFFT (wxCommandEvent& event) ImageFile& rIF = GetDocument()->getImageFile(); wxProgressDialog dlgProgress (wxString("IFFT"), wxString("IFFT Progress"), 1, m_frame, wxPD_APP_MODAL); rIF.ifft (rIF); + rIF.labelAdd ("IFFT Image"); m_bMinSpecified = false; m_bMaxSpecified = false; if (theApp->getSetModifyNewDocs()) @@ -413,12 +533,52 @@ ImageFileView::OnIFFT (wxCommandEvent& event) } #endif +void +ImageFileView::OnFourier (wxCommandEvent& event) +{ + ImageFile& rIF = GetDocument()->getImageFile(); + wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, m_frame, wxPD_APP_MODAL); + rIF.fourier (rIF); + rIF.labelAdd ("Fourier Image"); + m_bMinSpecified = false; + m_bMaxSpecified = false; + if (theApp->getSetModifyNewDocs()) + GetDocument()->Modify(TRUE); + GetDocument()->UpdateAllViews(this); +} void ImageFileView::OnInverseFourier (wxCommandEvent& event) { ImageFile& rIF = GetDocument()->getImageFile(); wxProgressDialog dlgProgress (wxString("Inverse Fourier"), wxString("Inverse Fourier Progress"), 1, m_frame, wxPD_APP_MODAL); rIF.inverseFourier (rIF); + rIF.labelAdd ("Inverse Fourier Image"); + m_bMinSpecified = false; + m_bMaxSpecified = false; + if (theApp->getSetModifyNewDocs()) + GetDocument()->Modify(TRUE); + GetDocument()->UpdateAllViews(this); +} + +void +ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event) +{ + ImageFile& rIF = GetDocument()->getImageFile(); + Fourier::shuffleNaturalToFourierOrder (rIF); + rIF.labelAdd ("Shuffle Natural To Fourier Order"); + m_bMinSpecified = false; + m_bMaxSpecified = false; + if (theApp->getSetModifyNewDocs()) + GetDocument()->Modify(TRUE); + GetDocument()->UpdateAllViews(this); +} + +void +ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event) +{ + ImageFile& rIF = GetDocument()->getImageFile(); + Fourier::shuffleFourierToNaturalOrder (rIF); + rIF.labelAdd ("Shuffle Fourier To Natural Order"); m_bMinSpecified = false; m_bMaxSpecified = false; if (theApp->getSetModifyNewDocs()) @@ -430,24 +590,30 @@ void ImageFileView::OnMagnitude (wxCommandEvent& event) { ImageFile& rIF = GetDocument()->getImageFile(); - rIF.magnitude (rIF); + if (rIF.isComplex()) { + rIF.magnitude (rIF); + rIF.labelAdd ("Magnitude of complex-image"); m_bMinSpecified = false; m_bMaxSpecified = false; if (theApp->getSetModifyNewDocs()) GetDocument()->Modify(TRUE); GetDocument()->UpdateAllViews(this); + } } void ImageFileView::OnPhase (wxCommandEvent& event) { ImageFile& rIF = GetDocument()->getImageFile(); - rIF.phase (rIF); + if (rIF.isComplex()) { + rIF.phase (rIF); + rIF.labelAdd ("Phase of complex-image"); m_bMinSpecified = false; m_bMaxSpecified = false; if (theApp->getSetModifyNewDocs()) GetDocument()->Modify(TRUE); GetDocument()->UpdateAllViews(this); + } } @@ -481,8 +647,9 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) file_menu->Append(wxID_SAVEAS, "Save &As..."); file_menu->Append(wxID_CLOSE, "&Close"); - file_menu->AppendSeparator(); + file_menu->AppendSeparator(); file_menu->Append(IFMENU_FILE_PROPERTIES, "P&roperties"); + file_menu->Append(IFMENU_FILE_EXPORT, "&Export..."); file_menu->AppendSeparator(); file_menu->Append(wxID_PRINT, "&Print..."); @@ -500,6 +667,13 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) process_menu->Append (IFMENU_PROCESS_LOG, "&Log"); process_menu->Append (IFMENU_PROCESS_EXP, "&Exp"); process_menu->AppendSeparator(); + process_menu->Append (IFMENU_PROCESS_ADD, "&Add"); + process_menu->Append (IFMENU_PROCESS_SUBTRACT, "Su&btract"); + process_menu->Append (IFMENU_PROCESS_MULTIPLY, "&Multiply"); + process_menu->Append (IFMENU_PROCESS_DIVIDE, "&Divide"); + process_menu->AppendSeparator(); + process_menu->Append (IFMENU_PROCESS_SCALESIZE, "S&cale Size..."); + process_menu->AppendSeparator(); #ifdef HAVE_FFTW process_menu->Append (IFMENU_PROCESS_FFT, "&FFT"); process_menu->Append (IFMENU_PROCESS_IFFT, "&IFFT"); @@ -509,6 +683,8 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) process_menu->Append (IFMENU_PROCESS_FOURIER, "&Fourier"); process_menu->Append (IFMENU_PROCESS_INVERSE_FOURIER, "&Inverse Fourier"); #endif + process_menu->Append (IFMENU_PROCESS_SHUFFLEFOURIERTONATURALORDER, "S&huffle Fourier to Natural Order"); + process_menu->Append (IFMENU_PROCESS_SHUFFLENATURALTOFOURIERORDER, "Shu&ffle Natural to Fourier Order"); process_menu->Append (IFMENU_PROCESS_MAGNITUDE, "&Magnitude"); process_menu->Append (IFMENU_PROCESS_PHASE, "&Phase"); @@ -542,7 +718,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) bool -ImageFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) +ImageFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) ) { m_frame = CreateChildFrame(doc, this); SetFrame (m_frame); @@ -645,6 +821,80 @@ ImageFileView::OnClose (bool deleteWindow) return true; } +void +ImageFileView::OnExport (wxCommandEvent& event) +{ + ImageFile& rIF = dynamic_cast(GetDocument())->getImageFile(); + ImageFileArrayConst v = rIF.getArray(); + int nx = rIF.nx(); + int ny = rIF.ny(); + if (v != NULL && nx != 0 && ny != 0) { + if (! m_bMinSpecified || ! m_bMaxSpecified) { + double min, max; + rIF.getMinMax (min, max); + if (! m_bMinSpecified) + m_dMinPixel = min; + if (! m_bMaxSpecified) + m_dMaxPixel = max; + } + + DialogExportParameters dialogExport (m_frame, m_iDefaultExportFormatID); + if (dialogExport.ShowModal() == wxID_OK) { + wxString strFormatName (dialogExport.getFormatName ()); + m_iDefaultExportFormatID = ImageFile::convertFormatNameToID (strFormatName.c_str()); + + wxString strExt; + wxString strWildcard; + if (m_iDefaultExportFormatID == ImageFile::FORMAT_PGM || m_iDefaultExportFormatID == ImageFile::FORMAT_PGMASCII) { + strExt = ".pgm"; + strWildcard = "PGM Files (*.pgm)|*.pgm"; + } +#ifdef HAVE_PNG + else if (m_iDefaultExportFormatID == ImageFile::FORMAT_PNG || m_iDefaultExportFormatID == ImageFile::FORMAT_PNG16) { + strExt = ".png"; + strWildcard = "PNG Files (*.png)|*.png"; + } +#endif + + const wxString& strFilename = wxFileSelector (wxString("Export Filename"), wxString(""), + wxString(""), strExt, strWildcard, wxOVERWRITE_PROMPT | wxHIDE_READONLY | wxSAVE); + if (strFilename) { + rIF.exportImage (strFormatName.c_str(), strFilename.c_str(), 1, 1, m_dMinPixel, m_dMaxPixel); + *theApp->getLog() << "Exported file " << strFilename << "\n"; + } + } + } +} + +void +ImageFileView::OnScaleSize (wxCommandEvent& event) +{ + ImageFile& rIF = GetDocument()->getImageFile(); + unsigned int iOldNX = rIF.nx(); + unsigned int iOldNY = rIF.ny(); + + DialogGetXYSize dialogGetXYSize (m_frame, "Set New X & Y Dimensions", iOldNX, iOldNY); + if (dialogGetXYSize.ShowModal() == wxID_OK) { + unsigned int iNewNX = dialogGetXYSize.getXSize(); + unsigned int iNewNY = dialogGetXYSize.getYSize(); + std::ostringstream os; + os << "Scale Size from (" << iOldNX << "," << iOldNY << ") to (" << iNewNX << "," << iNewNY << ")"; + ImageFileDocument* pScaledDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT)); + if (! pScaledDoc) { + sys_error (ERR_SEVERE, "Unable to create image file"); + return; + } + ImageFile& rScaledIF = pScaledDoc->getImageFile(); + rScaledIF.setArraySize (iNewNX, iNewNY); + rScaledIF.labelAdd (os.str().c_str()); + rIF.scaleImage (rScaledIF); + *theApp->getLog() << os.str().c_str() << "\n"; + if (theApp->getSetModifyNewDocs()) + pScaledDoc->Modify(TRUE); + pScaledDoc->UpdateAllViews (this); + pScaledDoc->GetFirstView()->OnUpdate (this, NULL); + } +} void ImageFileView::OnPlotRow (wxCommandEvent& event) @@ -896,7 +1146,7 @@ PhantomCanvas::PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos } void -PhantomCanvas::OnDraw(wxDC& dc) +PhantomCanvas::OnDraw (wxDC& dc) { if (m_pView) m_pView->OnDraw(& dc); @@ -936,12 +1186,14 @@ PhantomView::OnProperties (wxCommandEvent& event) const int idPhantom = GetDocument()->getPhantomID(); const wxString& namePhantom = GetDocument()->getPhantomName(); std::ostringstream os; - os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")\n"; - *theApp->getLog() << os.str().c_str(); + os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")" << "\n"; + const Phantom& rPhantom = GetDocument()->getPhantom(); + rPhantom.printDefinitions (os); #if DEBUG - const Phantom& rPhantom = GetDocument()->getPhantom(); - rPhantom.print(); + rPhantom.print (os); #endif + *theApp->getLog() << os.str().c_str() << "\n"; + wxMessageBox (os.str().c_str(), "Phantom Properties"); } @@ -1102,7 +1354,8 @@ PhantomView::CreateChildFrame(wxDocument *doc, wxView *view) file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom..."); file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter..."); - file_menu->Append(wxID_OPEN, "&Open..."); + file_menu->Append(wxID_OPEN, "&Open..."); + file_menu->Append(wxID_SAVEAS, "Save &As..."); file_menu->Append(wxID_CLOSE, "&Close"); file_menu->AppendSeparator(); @@ -1571,9 +1824,10 @@ PlotFileView::~PlotFileView(void) void PlotFileView::OnProperties (wxCommandEvent& event) { - const PlotFile& rProj = GetDocument()->getPlotFile(); + const PlotFile& rPlot = GetDocument()->getPlotFile(); std::ostringstream os; - os << "Columns: " << rProj.getNumColumns() << ", Records: " << rProj.getNumRecords() << "\n"; + os << "Columns: " << rPlot.getNumColumns() << ", Records: " << rPlot.getNumRecords() << "\n"; + rPlot.printHeaders (os); *theApp->getLog() << os.str().c_str(); wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Plot File Properties", wxOK | wxICON_INFORMATION); dialogMsg.ShowModal(); @@ -1605,9 +1859,10 @@ void PlotFileView::OnScaleMinMax (wxCommandEvent& event) { const PlotFile& rPlotFile = GetDocument()->getPlotFile(); - double min, max; - - if (! m_bMinSpecified && ! m_bMaxSpecified) { + double min; + double max; + + if (! m_bMinSpecified || ! m_bMaxSpecified) { if (! rPlotFile.getMinMax (1, min, max)) { *theApp->getLog() << "Error: unable to find Min/Max\n"; return; @@ -1739,7 +1994,6 @@ PlotFileView::OnDraw (wxDC* dc) void PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) { - if (m_canvas) { const PlotFile& rPlotFile = GetDocument()->getPlotFile(); const int iNColumns = rPlotFile.getNumColumns(); const int iNRecords = rPlotFile.getNumRecords(); @@ -1779,9 +2033,9 @@ PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) delete pdXaxis; delete pdY; } - - m_canvas->Refresh(); - } + + if (m_canvas) + m_canvas->Refresh(); } bool diff --git a/src/views.h b/src/views.h index 8d46ae3..024b885 100644 --- a/src/views.h +++ b/src/views.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: views.h,v 1.20 2001/01/01 10:14:34 kevin Exp $ +** $Id: views.h,v 1.21 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 @@ -55,6 +55,8 @@ private: double m_dMinPixel; double m_dMaxPixel; double m_dAutoScaleFactor; + + int m_iDefaultExportFormatID; public: ImageFileView(void); @@ -63,7 +65,10 @@ public: bool OnCreate(wxDocument *doc, long flags); void OnDraw(wxDC* dc); void OnUpdate(wxView *sender, wxObject *hint = NULL); - bool OnClose (bool deleteWindow = true); + bool OnClose (bool deleteWindow = true); + + void OnScaleSize (wxCommandEvent& event); + void OnExport (wxCommandEvent& event); void OnProperties (wxCommandEvent& event); void OnCompare (wxCommandEvent& event); void OnInvertValues (wxCommandEvent& event); @@ -71,8 +76,14 @@ public: void OnSquareRoot (wxCommandEvent& event); void OnLog (wxCommandEvent& event); void OnExp (wxCommandEvent& event); + void OnAdd (wxCommandEvent& event); + void OnSubtract (wxCommandEvent& event); + void OnMultiply (wxCommandEvent& event); + void OnDivide (wxCommandEvent& event); void OnFourier (wxCommandEvent& event); void OnInverseFourier (wxCommandEvent& event); + void OnShuffleNaturalToFourierOrder (wxCommandEvent& event); + void OnShuffleFourierToNaturalOrder (wxCommandEvent& event); #ifdef HAVE_FFTW void OnFFT (wxCommandEvent& event); void OnIFFT (wxCommandEvent& event); diff --git a/tools/phm2if.cpp b/tools/phm2if.cpp index e00e84e..e0ca9c8 100644 --- a/tools/phm2if.cpp +++ b/tools/phm2if.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phm2if.cpp,v 1.16 2000/12/17 23:30:48 kevin Exp $ +** $Id: phm2if.cpp,v 1.17 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 @@ -50,7 +50,7 @@ static struct option my_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: phm2if.cpp,v 1.16 2000/12/17 23:30:48 kevin Exp $"; +static const char* g_szIdStr = "$Id: phm2if.cpp,v 1.17 2001/01/02 05:34:57 kevin Exp $"; void phm2if_usage (const char *program) @@ -354,10 +354,11 @@ phm2if_main (int argc, char* argv[]) double dmin, dmax; int nscale; - printf ("Enter display size scale (nominal = 1): "); - scanf ("%d", &nscale); - printf ("Enter minimum and maximum densities (min, max): "); - scanf ("%lf %lf", &dmin, &dmax); + std::cout << "Enter display size scale (nominal = 1): "; + std::cin >> nscale; + std::cout ("Enter minimum and maximum densities (min, max): "; + std::cin >> dmin; + std::cin >> dmax; pImGlobal->displayScaling (nscale, dmin, dmax); } } diff --git a/tools/phm2pj.cpp b/tools/phm2pj.cpp index c47eec9..9d53148 100644 --- a/tools/phm2pj.cpp +++ b/tools/phm2pj.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phm2pj.cpp,v 1.19 2000/12/18 00:09:59 kevin Exp $ +** $Id: phm2pj.cpp,v 1.20 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 @@ -50,7 +50,7 @@ static struct option phm2pj_options[] = {0, 0, 0, 0} }; -static const char* g_szIdStr = "$Id: phm2pj.cpp,v 1.19 2000/12/18 00:09:59 kevin Exp $"; +static const char* g_szIdStr = "$Id: phm2pj.cpp,v 1.20 2001/01/02 05:34:57 kevin Exp $"; void @@ -353,13 +353,13 @@ phm2pj_main (int argc, char* argv[]) pjGlobal.setRemark (opt_desc); pjGlobal.write (opt_outfile); if (opt_verbose) { - phm.print(); - std::cout << std::endl; - std::ostringstream os; - pjGlobal.printScanInfo (os); - std::cout << os.str() << std::endl; - std::cout << " Remark: " << pjGlobal.remark() << std::endl; - std::cout << "Run time: " << pjGlobal.calcTime() << " seconds\n"; + phm.print (std::cout); + std::cout << std::endl; + std::ostringstream os; + pjGlobal.printScanInfo (os); + std::cout << os.str() << std::endl; + std::cout << " Remark: " << pjGlobal.remark() << std::endl; + std::cout << "Run time: " << pjGlobal.calcTime() << " seconds\n"; } } -- 2.34.1