r328: *** empty log message ***
[ctsim.git] / src / views.cpp
index 93d49b336da6917fd89d3ffce46677b70a07754b..3ec3b6bdae002955050f22087c48926cf07dcf42 100644 (file)
@@ -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)\r
+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)\r
@@ -177,8 +178,15 @@ EVT_MENU(IFMENU_PROCESS_SQUARE, ImageFileView::OnSquare)
 EVT_MENU(IFMENU_PROCESS_SQRT, ImageFileView::OnSquareRoot)\r
 EVT_MENU(IFMENU_PROCESS_LOG, ImageFileView::OnLog)\r
 EVT_MENU(IFMENU_PROCESS_EXP, ImageFileView::OnExp)\r
+EVT_MENU(IFMENU_PROCESS_ADD, ImageFileView::OnAdd)\r
+EVT_MENU(IFMENU_PROCESS_SUBTRACT, ImageFileView::OnSubtract)\r
+EVT_MENU(IFMENU_PROCESS_MULTIPLY, ImageFileView::OnMultiply)\r
+EVT_MENU(IFMENU_PROCESS_DIVIDE, ImageFileView::OnDivide)\r
 EVT_MENU(IFMENU_PROCESS_FOURIER, ImageFileView::OnFourier)\r
+EVT_MENU(IFMENU_PROCESS_SCALESIZE, ImageFileView::OnScaleSize)\r
 EVT_MENU(IFMENU_PROCESS_INVERSE_FOURIER, ImageFileView::OnInverseFourier)\r
+EVT_MENU(IFMENU_PROCESS_SHUFFLEFOURIERTONATURALORDER, ImageFileView::OnShuffleFourierToNaturalOrder)\r
+EVT_MENU(IFMENU_PROCESS_SHUFFLENATURALTOFOURIERORDER, ImageFileView::OnShuffleNaturalToFourierOrder)\r
 #ifdef HAVE_FFTW\r
 EVT_MENU(IFMENU_PROCESS_FFT, ImageFileView::OnFFT)\r
 EVT_MENU(IFMENU_PROCESS_IFFT, ImageFileView::OnIFFT)\r
@@ -191,7 +199,8 @@ END_EVENT_TABLE()
 
 ImageFileView::ImageFileView(void) 
 : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false)
-{
+{\r
+  m_iDefaultExportFormatID = ImageFile::FORMAT_PNG;\r
 }
 
 ImageFileView::~ImageFileView(void)
@@ -221,6 +230,10 @@ ImageFileView::OnProperties (wxCommandEvent& event)
       rIF.statistics (rIF.getImaginaryArray(), min, max, mean, mode, median, stddev);\r
       os << "\nImaginary: min: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmedian: "<<median<<"\nmode: "<<mode<<"\nstddev: "<<stddev << "\n";\r
     }\r
+    if (rIF.nLabels() > 0) {\r
+      os << "\n";\r
+      rIF.printLabelsBrief (os);\r
+    }\r
     *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);\r
       os << rIF.getFilename() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";\r
       rCompareIF.statistics (min, max, mean, mode, median, stddev);\r
-      os << pCompareDoc->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";\r
+      os << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";\r
       os << "\n";\r
       double d, r, e;\r
       rIF.comparativeStatistics (rCompareIF, d, r, e);\r
@@ -327,6 +340,7 @@ ImageFileView::OnInvertValues (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.invertPixelValues (rIF);\r
+  rIF.labelAdd ("Invert Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
@@ -337,6 +351,7 @@ ImageFileView::OnSquare (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.square (rIF);\r
+  rIF.labelAdd ("Square Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
@@ -347,6 +362,7 @@ ImageFileView::OnSquareRoot (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.sqrt (rIF);\r
+  rIF.labelAdd ("Square-root Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
@@ -357,6 +373,7 @@ ImageFileView::OnLog (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.log (rIF);\r
+  rIF.labelAdd ("Logrithm base-e Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
@@ -367,24 +384,125 @@ ImageFileView::OnExp (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.exp (rIF);\r
+  rIF.labelAdd ("Exponent base-e Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
 }\r
 \r
 void\r
-ImageFileView::OnFourier (wxCommandEvent& event)\r
+ImageFileView::OnAdd (wxCommandEvent& event)\r
 {\r
-  ImageFile& rIF = GetDocument()->getImageFile();\r
-  wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);\r
-  rIF.fourier (rIF);\r
-  m_bMinSpecified = false;\r
-  m_bMaxSpecified = false;\r
-  if (theApp->getSetModifyNewDocs())\r
-    GetDocument()->Modify(TRUE);\r
-  GetDocument()->UpdateAllViews(this);\r
+  std::vector<ImageFileDocument*> vecIF;\r
+  theApp->getCompatibleImages (GetDocument(), vecIF);\r
+  \r
+  if (vecIF.size() == 0) {\r
+    wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
+  } else {\r
+    DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Add", vecIF, false);\r
+    \r
+    if (dialogGetCompare.ShowModal() == wxID_OK) {\r
+      ImageFile& rIF = GetDocument()->getImageFile();\r
+      ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
+      const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
+      rIF.addImages (rRHSIF, rIF);\r
+      std::ostringstream os;\r
+      os << "Add image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and " \r
+        << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
+      rIF.labelAdd (os.str().c_str());\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      if (theApp->getSetModifyNewDocs())\r
+        GetDocument()->Modify(TRUE);\r
+      GetDocument()->UpdateAllViews(this);\r
+    }\r
+  }\r
 }\r
 \r
+void\r
+ImageFileView::OnSubtract (wxCommandEvent& event)\r
+{\r
+  std::vector<ImageFileDocument*> vecIF;\r
+  theApp->getCompatibleImages (GetDocument(), vecIF);\r
+  \r
+  if (vecIF.size() == 0) {\r
+    wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
+  } else {\r
+    DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Subtract", vecIF, false);\r
+    \r
+    if (dialogGetCompare.ShowModal() == wxID_OK) {\r
+      ImageFile& rIF = GetDocument()->getImageFile();\r
+      ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
+      const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
+      rIF.subtractImages (rRHSIF, rIF);\r
+      std::ostringstream os;\r
+      os << "Subtract image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() \r
+        << " and " << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
+      rIF.labelAdd (os.str().c_str());\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      if (theApp->getSetModifyNewDocs())\r
+        GetDocument()->Modify(TRUE);\r
+      GetDocument()->UpdateAllViews(this);\r
+    }\r
+  }\r
+}\r
+\r
+void\r
+ImageFileView::OnMultiply (wxCommandEvent& event)\r
+{\r
+  std::vector<ImageFileDocument*> vecIF;\r
+  theApp->getCompatibleImages (GetDocument(), vecIF);\r
+  \r
+  if (vecIF.size() == 0) {\r
+    wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
+  } else {\r
+    DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Multiply", vecIF, false);\r
+    \r
+    if (dialogGetCompare.ShowModal() == wxID_OK) {\r
+      ImageFile& rIF = GetDocument()->getImageFile();\r
+      ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
+      const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
+      rIF.multiplyImages (rRHSIF, rIF);\r
+      std::ostringstream os;\r
+      os << "Multiply image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() \r
+        << " and " << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
+      rIF.labelAdd (os.str().c_str());\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      if (theApp->getSetModifyNewDocs())\r
+        GetDocument()->Modify(TRUE);\r
+      GetDocument()->UpdateAllViews(this);\r
+    }\r
+  }\r
+}\r
+\r
+void\r
+ImageFileView::OnDivide (wxCommandEvent& event)\r
+{\r
+  std::vector<ImageFileDocument*> vecIF;\r
+  theApp->getCompatibleImages (GetDocument(), vecIF);\r
+  \r
+  if (vecIF.size() == 0) {\r
+    wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
+  } else {\r
+    DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Divide", vecIF, false);\r
+    \r
+    if (dialogGetCompare.ShowModal() == wxID_OK) {\r
+      ImageFile& rIF = GetDocument()->getImageFile();\r
+      ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
+      const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
+      rIF.divideImages (rRHSIF, rIF);\r
+      std::ostringstream os;\r
+      os << "Divide image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() \r
+        << " by " << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
+      rIF.labelAdd (os.str().c_str());\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      if (theApp->getSetModifyNewDocs())\r
+        GetDocument()->Modify(TRUE);\r
+      GetDocument()->UpdateAllViews(this);\r
+    }\r
+  }\r
+}\r
+\r
+\r
 #ifdef HAVE_FFTW\r
 void\r
 ImageFileView::OnFFT (wxCommandEvent& event)\r
@@ -392,6 +510,7 @@ ImageFileView::OnFFT (wxCommandEvent& event)
   ImageFile& rIF = GetDocument()->getImageFile();\r
   wxProgressDialog dlgProgress (wxString("FFT"), wxString("FFT Progress"), 1, m_frame, wxPD_APP_MODAL);\r
   rIF.fft (rIF);\r
+  rIF.labelAdd ("FFT Image");\r
   m_bMinSpecified = false;\r
   m_bMaxSpecified = false;\r
   if (theApp->getSetModifyNewDocs())\r
@@ -405,6 +524,7 @@ ImageFileView::OnIFFT (wxCommandEvent& event)
   ImageFile& rIF = GetDocument()->getImageFile();\r
   wxProgressDialog dlgProgress (wxString("IFFT"), wxString("IFFT Progress"), 1, m_frame, wxPD_APP_MODAL);\r
   rIF.ifft (rIF);\r
+  rIF.labelAdd ("IFFT Image");\r
   m_bMinSpecified = false;\r
   m_bMaxSpecified = false;\r
   if (theApp->getSetModifyNewDocs())\r
@@ -413,12 +533,52 @@ ImageFileView::OnIFFT (wxCommandEvent& event)
 }\r
 #endif\r
 \r
+void\r
+ImageFileView::OnFourier (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);\r
+  rIF.fourier (rIF);\r
+  rIF.labelAdd ("Fourier Image");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+}\r
 void\r
 ImageFileView::OnInverseFourier (wxCommandEvent& event)\r
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   wxProgressDialog dlgProgress (wxString("Inverse Fourier"), wxString("Inverse Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);\r
   rIF.inverseFourier (rIF);\r
+  rIF.labelAdd ("Inverse Fourier Image");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+}\r
+\r
+void\r
+ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  Fourier::shuffleNaturalToFourierOrder (rIF);\r
+  rIF.labelAdd ("Shuffle Natural To Fourier Order");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+}\r
+\r
+void\r
+ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  Fourier::shuffleFourierToNaturalOrder (rIF);\r
+  rIF.labelAdd ("Shuffle Fourier To Natural Order");\r
   m_bMinSpecified = false;\r
   m_bMaxSpecified = false;\r
   if (theApp->getSetModifyNewDocs())\r
@@ -430,24 +590,30 @@ void
 ImageFileView::OnMagnitude (wxCommandEvent& event)\r
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
-  rIF.magnitude (rIF);\r
+  if (rIF.isComplex()) {\r
+    rIF.magnitude (rIF);\r
+    rIF.labelAdd ("Magnitude of complex-image");\r
   m_bMinSpecified = false;\r
   m_bMaxSpecified = false;\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
+  }\r
 }\r
 \r
 void\r
 ImageFileView::OnPhase (wxCommandEvent& event)\r
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
-  rIF.phase (rIF);\r
+  if (rIF.isComplex()) {\r
+    rIF.phase (rIF);\r
+    rIF.labelAdd ("Phase of complex-image");\r
   m_bMinSpecified = false;\r
   m_bMaxSpecified = false;\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
+  }\r
 }\r
 \r
 \r
@@ -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();\r
   file_menu->Append(IFMENU_FILE_PROPERTIES, "P&roperties");
+  file_menu->Append(IFMENU_FILE_EXPORT, "&Export...");\r
   
   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");\r
   process_menu->Append (IFMENU_PROCESS_EXP, "&Exp");\r
   process_menu->AppendSeparator();\r
+  process_menu->Append (IFMENU_PROCESS_ADD, "&Add");\r
+  process_menu->Append (IFMENU_PROCESS_SUBTRACT, "Su&btract");\r
+  process_menu->Append (IFMENU_PROCESS_MULTIPLY, "&Multiply");\r
+  process_menu->Append (IFMENU_PROCESS_DIVIDE, "&Divide");\r
+  process_menu->AppendSeparator();\r
+  process_menu->Append (IFMENU_PROCESS_SCALESIZE, "S&cale Size...");\r
+  process_menu->AppendSeparator();\r
 #ifdef HAVE_FFTW\r
   process_menu->Append (IFMENU_PROCESS_FFT, "&FFT");\r
   process_menu->Append (IFMENU_PROCESS_IFFT, "&IFFT");\r
@@ -509,6 +683,8 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   process_menu->Append (IFMENU_PROCESS_FOURIER, "&Fourier");\r
   process_menu->Append (IFMENU_PROCESS_INVERSE_FOURIER, "&Inverse Fourier");\r
 #endif\r
+  process_menu->Append (IFMENU_PROCESS_SHUFFLEFOURIERTONATURALORDER, "S&huffle Fourier to Natural Order");\r
+  process_menu->Append (IFMENU_PROCESS_SHUFFLENATURALTOFOURIERORDER, "Shu&ffle Natural to Fourier Order");\r
   process_menu->Append (IFMENU_PROCESS_MAGNITUDE, "&Magnitude");\r
   process_menu->Append (IFMENU_PROCESS_PHASE, "&Phase");\r
 \r
@@ -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;
 }
 \r
+void\r
+ImageFileView::OnExport (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();\r
+  ImageFileArrayConst v = rIF.getArray();\r
+  int nx = rIF.nx();\r
+  int ny = rIF.ny();\r
+  if (v != NULL && nx != 0 && ny != 0) {\r
+    if (! m_bMinSpecified || ! m_bMaxSpecified) {\r
+      double min, max;\r
+      rIF.getMinMax (min, max);\r
+      if (! m_bMinSpecified)\r
+        m_dMinPixel = min;\r
+      if (! m_bMaxSpecified)\r
+        m_dMaxPixel = max;\r
+    }\r
+\r
+    DialogExportParameters dialogExport (m_frame, m_iDefaultExportFormatID);\r
+    if (dialogExport.ShowModal() == wxID_OK) {\r
+      wxString strFormatName (dialogExport.getFormatName ());\r
+      m_iDefaultExportFormatID = ImageFile::convertFormatNameToID (strFormatName.c_str());\r
+\r
+      wxString strExt;\r
+      wxString strWildcard;\r
+      if (m_iDefaultExportFormatID == ImageFile::FORMAT_PGM || m_iDefaultExportFormatID == ImageFile::FORMAT_PGMASCII) {\r
+        strExt = ".pgm";\r
+        strWildcard = "PGM Files (*.pgm)|*.pgm";\r
+      }\r
+#ifdef HAVE_PNG\r
+      else if (m_iDefaultExportFormatID == ImageFile::FORMAT_PNG || m_iDefaultExportFormatID == ImageFile::FORMAT_PNG16) {\r
+        strExt = ".png";\r
+        strWildcard = "PNG Files (*.png)|*.png";\r
+      }\r
+#endif\r
+\r
+      const wxString& strFilename = wxFileSelector (wxString("Export Filename"), wxString(""), \r
+        wxString(""), strExt, strWildcard, wxOVERWRITE_PROMPT | wxHIDE_READONLY | wxSAVE);\r
+      if (strFilename) {\r
+        rIF.exportImage (strFormatName.c_str(), strFilename.c_str(), 1, 1, m_dMinPixel, m_dMaxPixel);\r
+        *theApp->getLog() << "Exported file " << strFilename << "\n";\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void\r
+ImageFileView::OnScaleSize (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  unsigned int iOldNX = rIF.nx();\r
+  unsigned int iOldNY = rIF.ny();\r
+\r
+  DialogGetXYSize dialogGetXYSize (m_frame, "Set New X & Y Dimensions", iOldNX, iOldNY);\r
+  if (dialogGetXYSize.ShowModal() == wxID_OK) {\r
+    unsigned int iNewNX = dialogGetXYSize.getXSize();\r
+    unsigned int iNewNY = dialogGetXYSize.getYSize();\r
+    std::ostringstream os;\r
+    os << "Scale Size from (" << iOldNX << "," << iOldNY << ") to (" << iNewNX << "," << iNewNY << ")";\r
+    ImageFileDocument* pScaledDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
+    if (! pScaledDoc) {\r
+      sys_error (ERR_SEVERE, "Unable to create image file");\r
+      return;\r
+    }\r
+    ImageFile& rScaledIF = pScaledDoc->getImageFile();\r
+    rScaledIF.setArraySize (iNewNX, iNewNY);\r
+    rScaledIF.labelAdd (os.str().c_str());\r
+    rIF.scaleImage (rScaledIF);\r
+    *theApp->getLog() << os.str().c_str() << "\n";\r
+    if (theApp->getSetModifyNewDocs())\r
+      pScaledDoc->Modify(TRUE);\r
+    pScaledDoc->UpdateAllViews (this);\r
+    pScaledDoc->GetFirstView()->OnUpdate (this, NULL);\r
+  }\r
+}\r
 \r
 void\r
 ImageFileView::OnPlotRow (wxCommandEvent& event)\r
@@ -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";\r
+  const Phantom& rPhantom = GetDocument()->getPhantom();\r
+  rPhantom.printDefinitions (os);
 #if DEBUG
-  const Phantom& rPhantom = GetDocument()->getPhantom();
-  rPhantom.print();
+  rPhantom.print (os);
 #endif
+  *theApp->getLog() << os.str().c_str() << "\n";\r
+  wxMessageBox (os.str().c_str(), "Phantom Properties");\r
 }
 
 
@@ -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...");\r
-  file_menu->Append(wxID_OPEN, "&Open...");
+  file_menu->Append(wxID_OPEN, "&Open...");\r
+  file_menu->Append(wxID_SAVEAS, "Save &As...");\r
   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;\r
-  os << "Columns: " << rProj.getNumColumns() << ", Records: " << rProj.getNumRecords() << "\n";
+  os << "Columns: " << rPlot.getNumColumns() << ", Records: " << rPlot.getNumRecords() << "\n";\r
+  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)\r
 {\r
   const PlotFile& rPlotFile = GetDocument()->getPlotFile();\r
-  double min, max;\r
-  \r
-  if (! m_bMinSpecified && ! m_bMaxSpecified) {\r
+  double min;\r
+  double max;\r
+\r
+  if (! m_bMinSpecified || ! m_bMaxSpecified) {\r
     if (! rPlotFile.getMinMax (1, min, max)) {\r
       *theApp->getLog() << "Error: unable to find Min/Max\n";\r
       return;\r
@@ -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();\r
     const int iNColumns = rPlotFile.getNumColumns();\r
     const int iNRecords = rPlotFile.getNumRecords();\r
@@ -1779,9 +2033,9 @@ PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
       delete pdXaxis;\r
       delete pdY;\r
     }\r
-    \r
-    m_canvas->Refresh();\r
-  }
+\r
+    if (m_canvas)\r
+      m_canvas->Refresh();\r
 }
 
 bool