From: Kevin M. Rosenberg Date: Sat, 15 Jul 2000 08:36:13 +0000 (+0000) Subject: r148: *** empty log message *** X-Git-Tag: debian-4.5.3-3~869 X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=commitdiff_plain;h=e4c1f7f8eb87558c3abf3bf1d20732361f425351 r148: *** empty log message *** --- diff --git a/ChangeLog b/ChangeLog index 3ca8243..b6451cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -2.0.0-b4 - 7/11/00 +2.0.0-b4 - 7/13/00 Fixed compiler warnings at -Wall level Began work on CTSim program to be graphical front-end of all functions Moved current src/*.cpp to tools/*.cpp diff --git a/INSTALL b/INSTALL index f134ef0..4b46c75 100644 --- a/INSTALL +++ b/INSTALL @@ -13,7 +13,16 @@ libpng (ftp://ftp.uu.net/graphics/png/src) not work. fftw (http://www.fftw.org) - Fastest Fourier Transform in the West + Fastest Fourier Transform in the West. Currently, the only FFT + routines used by CTSim. + +wxWindows (http://www.wxwindows.org) + Used by CTSim (src/*) graphic front-end + +g2 (http://g2.sourceforge.net) + Currently, used partially by SGP (Simple Graphics Package) for +graphical display by command-line tools (tools/*). This library +will likely be deprecated in favor of wxWindows. lam (http://www.mpi.nd.edu/lam/) There is support is MPI clustering. I use this code at home for my diff --git a/NEWS b/NEWS index 3361499..c6a1599 100644 --- a/NEWS +++ b/NEWS @@ -1,2 +1,20 @@ -6/17/2000 - CTSim converted to C++ and has cross-platform compatible data files. +Version 2.0 of CTSim is near completion! + + +New Features of CTSim version 2.0: + +- Entire code-base, except for SGP & EZPlot, cleaned up and + re-written. All code converted to C++. + +- Integrated G2 library for graphical display from command line tools + +- Graphic front-end (ctsim) initial implemention. Can display + projection and image files. + +- Added frequency-based filtering. Can provide significant speed-up + in reconstructions compared to convolution-based filtering. + +- Added highly-optimized backprojection method (idiff3) + +- New command-line tools added for image statistics and comparisons with + both text and graphical outputs. diff --git a/TODO b/TODO index 26437f6..ceeae85 100644 --- a/TODO +++ b/TODO @@ -1,30 +1,7 @@ MISCELLANEOUS ============= -Integrate low-level X11 graphics, replace all low-level driver code in -libgraph. All the high-level graphics routines are in place. +Convert SGP graphics to wxWindows. -PROPOSED MENU STRUCTURE -======================= -File - New - Phantom - Open - SDF - -Process - Simulate CT process (active only when phantom outline shown) - Rasterize Phantom (active only when phantom outline shown) - Reconstruct CT data (active only when raysum data is shown) - -Filter - (Various single and dual image transformations) - -Compare - Compare 2 images - 2D grayscale subtraction - 1D column plots - Single Image statistics - diff --git a/include/ezplot.h b/include/ezplot.h index 11ac4e5..30fe4e5 100644 --- a/include/ezplot.h +++ b/include/ezplot.h @@ -2,7 +2,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ezplot.h,v 1.8 2000/06/20 17:54:51 kevin Exp $ +** $Id: ezplot.h,v 1.9 2000/07/15 08:36:13 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 @@ -314,8 +314,8 @@ extern bool ezplot_firstcall; /* set to false on first call to EZSET or EZPLOT /* ezplot.cpp */ -SGP_ID ezplot(float x[], double y[], int num); -SGP_ID ezplot(double x[], double y[], int num); +SGP_ID ezplot (const float x[], const double y[], int num); +SGP_ID ezplot (const double x[], const double y[], int num); void ezinit(void); void ezfree(void); void ezclear(void); diff --git a/include/phantom.h b/include/phantom.h index 09af2b3..ad8b0f8 100644 --- a/include/phantom.h +++ b/include/phantom.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phantom.h,v 1.5 2000/07/13 07:03:21 kevin Exp $ +** $Id: phantom.h,v 1.6 2000/07/15 08:36:13 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 @@ -109,6 +109,8 @@ class PhantomElement static int numCirclePoints (double theta); + PhantomElement (const PhantomElement& rhs); // copy constructor + PhantomElement& operator= (const PhantomElement&); // assignment operator }; @@ -207,6 +209,9 @@ class Phantom static const char* convertPhantomIDToName (const PhantomID phmID); void init(void); + + Phantom (const Phantom& rhs); // copy constructor + Phantom& operator= (const Phantom&); // assignment operator }; typedef slist::iterator PElemIterator; diff --git a/include/projections.h b/include/projections.h index b1ee7fe..095095b 100644 --- a/include/projections.h +++ b/include/projections.h @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: projections.h,v 1.9 2000/07/13 07:03:21 kevin Exp $ +** $Id: projections.h,v 1.10 2000/07/15 08:36:13 kevin Exp $ ** ** ** This program is free software; you can redistribute it and/or modify @@ -53,7 +53,7 @@ class Projections bool detarrayRead (fnetorderstream& fs, DetectorArray& darray, const int view_num); bool detarrayWrite (fnetorderstream& fs, const DetectorArray& darray, const int view_num); - bool reconstruct (ImageFile& im, const char* const filterName, double filt_param, const char* const filterMethodName, const int zeropad, const char* const interpName, int interp_param, const char* const backprojName, const int trace); + bool reconstruct (ImageFile& im, const char* const filterName, double filt_param, const char* const filterMethodName, const int zeropad, const char* const interpName, int interp_param, const char* const backprojName, const int trace) const; void setNView (int nView); // used in MPI to restrict # of views void setRotInc (double rotInc) { m_rotInc = rotInc;} diff --git a/libctgraphics/ezplot.cpp b/libctgraphics/ezplot.cpp index 05ca13f..7b7bb55 100644 --- a/libctgraphics/ezplot.cpp +++ b/libctgraphics/ezplot.cpp @@ -6,7 +6,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: ezplot.cpp,v 1.5 2000/07/13 07:03:21 kevin Exp $ +** $Id: ezplot.cpp,v 1.6 2000/07/15 08:36:13 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 @@ -124,7 +124,7 @@ static char y_numfmt[20]; /* format to print y tick labels */ SGP_ID -ezplot (float x[], double y[], int num) +ezplot (const float x[], const double y[], int num) { double dx [num]; @@ -136,7 +136,7 @@ ezplot (float x[], double y[], int num) SGP_ID -ezplot (double x[], double y[], int num) +ezplot (const double x[], const double y[], int num) { unsigned int size; SGP_ID gid = NULL; diff --git a/libctsim/filter.cpp b/libctsim/filter.cpp index d22e99f..1c9e95b 100644 --- a/libctsim/filter.cpp +++ b/libctsim/filter.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: filter.cpp,v 1.17 2000/07/13 07:03:21 kevin Exp $ +** $Id: filter.cpp,v 1.18 2000/07/15 08:36:13 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 @@ -139,7 +139,7 @@ SignalFilter::init (const FilterID filterID, const FilterMethodID filterMethodID #endif } - if (m_idFilterMethod == FILTER_METHOD_FOURIER || FILTER_METHOD_FOURIER_TABLE || m_idFilterMethod == FILTER_METHOD_FFT + if (m_idFilterMethod == FILTER_METHOD_FOURIER || m_idFilterMethod == FILTER_METHOD_FOURIER_TABLE || m_idFilterMethod == FILTER_METHOD_FFT #if HAVE_FFTW || m_idFilterMethod == FILTER_METHOD_FFTW || m_idFilterMethod == FILTER_METHOD_RFFTW #endif @@ -152,7 +152,8 @@ SignalFilter::init (const FilterID filterID, const FilterMethodID filterMethodID nextPowerOf2++; nextPowerOf2 += (m_zeropad - 1); m_nFilterPoints = 1 << nextPowerOf2; - cout << "nFilterPoints = " << m_nFilterPoints << endl; + if (m_traceLevel >= TRACE_TEXT) + cout << "nFilterPoints = " << m_nFilterPoints << endl; } m_nOutputPoints = m_nFilterPoints * m_preinterpolationFactor; m_filterMin = -1. / (2 * m_signalInc); diff --git a/libctsim/imagefile.cpp b/libctsim/imagefile.cpp index 3a1483d..1b1660d 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.8 2000/07/13 07:03:21 kevin Exp $ +** $Id: imagefile.cpp,v 1.9 2000/07/15 08:36:13 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 @@ -59,7 +59,6 @@ ImageFile::display (void) const int ImageFile::displayScaling (const int scale, const ImageFileValue pmin, const ImageFileValue pmax) const { - int grayscale[256]; int nx = m_nx; int ny = m_ny; ImageFileArrayConst v = getArray(); @@ -71,7 +70,7 @@ ImageFile::displayScaling (const int scale, const ImageFileValue pmin, const Ima double view_scale = 255 / (pmax - pmin); int id_X11 = g2_open_X11 (nx * scale, ny * scale); - + int grayscale[256]; for (int i = 0; i < 256; i++) { double cval = i / 255.; grayscale[i] = g2_ink (id_X11, cval, cval, cval); diff --git a/libctsim/phantom.cpp b/libctsim/phantom.cpp index dba6576..7acfc3f 100644 --- a/libctsim/phantom.cpp +++ b/libctsim/phantom.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: phantom.cpp,v 1.6 2000/07/13 07:03:21 kevin Exp $ +** $Id: phantom.cpp,v 1.7 2000/07/15 08:36:13 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 @@ -294,17 +294,15 @@ Phantom::show (void) const ymax = ymin + wsize; printf("Drawing Phantom:\n\n"); - printf(" data limits: %9.3g, %9.3g, %9.3g, %9.3g\n", - m_xmin, m_ymin, m_xmax, m_ymax); - printf(" window size: %9.3g, %9.3g, %9.3g, %9.3g\n", - xmin, ymin, xmax, ymax); + printf(" data limits: %9.3g, %9.3g, %9.3g, %9.3g\n", m_xmin, m_ymin, m_xmax, m_ymax); + printf(" window size: %9.3g, %9.3g, %9.3g, %9.3g\n", xmin, ymin, xmax, ymax); - gid = sgp2_init(0, 0, "Phantom Show"); + gid = sgp2_init (0, 0, "Phantom Show"); sgp2_window (xmin, ymin, xmax, ymax); draw(); - termgrf2(); + sgp2_close (gid); } #endif @@ -338,17 +336,17 @@ Phantom::draw (void) const void Phantom::addStdRowland (void) { - addPElem("ellipse", 0.0000, 0.0000, 0.6900, 0.9200, 0.0, 1.00); - addPElem("ellipse", 0.0000, -0.0184, 0.6624, 0.8740, 0.0, -0.98); - addPElem("ellipse", 0.2200, 0.0000, 0.1100, 0.3100, -18.0, -0.02); - addPElem("ellipse", -0.2200, 0.0000, 0.1600, 0.4100, 18.0, -0.02); - addPElem("ellipse", 0.0000, 0.3500, 0.2100, 0.2500, 0.0, 0.01); - addPElem("ellipse", 0.0000, 0.1000, 0.0460, 0.0460, 0.0, 0.01); - addPElem("ellipse", 0.0000, -0.1000, 0.0460, 0.0460, 0.0, 0.01); - addPElem("ellipse", -0.0800, -0.6050, 0.0460, 0.0230, 0.0, 0.01); - addPElem("ellipse", 0.0000, -0.6050, 0.0230, 0.0230, 0.0, 0.01); - addPElem("ellipse", 0.0600, -0.6050, 0.0230, 0.0230, 0.0, 0.01); - addPElem("ellipse", 0.5538, -0.3858, 0.0330, 0.2060, -18.0, 0.03); + addPElem ("ellipse", 0.0000, 0.0000, 0.6900, 0.9200, 0.0, 1.00); + addPElem ("ellipse", 0.0000, -0.0184, 0.6624, 0.8740, 0.0, -0.98); + addPElem ("ellipse", 0.2200, 0.0000, 0.1100, 0.3100, -18.0, -0.02); + addPElem ("ellipse", -0.2200, 0.0000, 0.1600, 0.4100, 18.0, -0.02); + addPElem ("ellipse", 0.0000, 0.3500, 0.2100, 0.2500, 0.0, 0.01); + addPElem ("ellipse", 0.0000, 0.1000, 0.0460, 0.0460, 0.0, 0.01); + addPElem ("ellipse", 0.0000, -0.1000, 0.0460, 0.0460, 0.0, 0.01); + addPElem ("ellipse", -0.0800, -0.6050, 0.0460, 0.0230, 0.0, 0.01); + addPElem ("ellipse", 0.0000, -0.6050, 0.0230, 0.0230, 0.0, 0.01); + addPElem ("ellipse", 0.0600, -0.6050, 0.0230, 0.0230, 0.0, 0.01); + addPElem ("ellipse", 0.5538, -0.3858, 0.0330, 0.2060, -18.0, 0.03); } void @@ -369,27 +367,28 @@ Phantom::addStdRowlandBordered (void) void Phantom::addStdHerman (void) { - addPElem("ellipse", 0.000, 1.50, 0.375, 0.3000, 90.00, -0.003); - addPElem("ellipse", 0.675, -0.75, 0.225, 0.1500, 140.00, 0.010); - addPElem("ellipse", 0.750, 1.50, 0.375, 0.2250, 50.00, 0.003); - addPElem("segment", 1.375, -7.50, 1.100, 0.6250, 19.20, -0.204); - addPElem("segment", 1.375, -7.50, 1.100, 4.3200, 19.21, 0.204); - addPElem("segment", 0.000, -2.25, 1.125, 0.3750, 0.00, -0.003); - addPElem("segment", 0.000, -2.25, 1.125, 3.0000, 0.00, 0.003); - addPElem("segment", -1.000, 3.75, 1.000, 0.5000, 135.00, -0.003); - addPElem("segment", -1.000, 3.75, 1.000, 3.0000, 135.00, 0.003); - addPElem("segment", 1.000, 3.75, 1.000, 0.5000, 225.00, -0.003); - addPElem("segment", 1.000, 3.75, 1.000, 3.0000, 225.00, 0.003); - addPElem("triangle", 5.025, 3.75, 1.125, 0.5000, 110.75, 0.206); - addPElem("triangle",-5.025, 3.75, 1.125, 0.9000,-110.75, 0.206); - addPElem("ellipse", 0.000, 0.00, 8.625, 6.4687, 90.00, 0.416); - addPElem("ellipse", 0.000, 0.00, 7.875, 5.7187, 90.00, -0.206); + addPElem ("ellipse", 0.000, 1.50, 0.375, 0.3000, 90.00, -0.003); + addPElem ("ellipse", 0.675, -0.75, 0.225, 0.1500, 140.00, 0.010); + addPElem ("ellipse", 0.750, 1.50, 0.375, 0.2250, 50.00, 0.003); + addPElem ("segment", 1.375, -7.50, 1.100, 0.6250, 19.20, -0.204); + addPElem ("segment", 1.375, -7.50, 1.100, 4.3200, 19.21, 0.204); + addPElem ("segment", 0.000, -2.25, 1.125, 0.3750, 0.00, -0.003); + addPElem ("segment", 0.000, -2.25, 1.125, 3.0000, 0.00, 0.003); + addPElem ("segment", -1.000, 3.75, 1.000, 0.5000, 135.00, -0.003); + addPElem ("segment", -1.000, 3.75, 1.000, 3.0000, 135.00, 0.003); + addPElem ("segment", 1.000, 3.75, 1.000, 0.5000, 225.00, -0.003); + addPElem ("segment", 1.000, 3.75, 1.000, 3.0000, 225.00, 0.003); + addPElem ("triangle", 5.025, 3.75, 1.125, 0.5000, 110.75, 0.206); + addPElem ("triangle",-5.025, 3.75, 1.125, 0.9000,-110.75, 0.206); + addPElem ("ellipse", 0.000, 0.00, 8.625, 6.4687, 90.00, 0.416); + addPElem ("ellipse", 0.000, 0.00, 7.875, 5.7187, 90.00, -0.206); } void Phantom::addStdHermanBordered (void) { - addPElem("ellipse", 0., 0., 6.6, 5.9, 90., 0.); + addStdHerman(); + addPElem ("ellipse", 0.000, 0.000, 8.650, 8.650, 0.00, 0.000); } diff --git a/libctsim/projections.cpp b/libctsim/projections.cpp index 69c4d08..a29d7c5 100644 --- a/libctsim/projections.cpp +++ b/libctsim/projections.cpp @@ -8,7 +8,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: projections.cpp,v 1.14 2000/07/13 07:03:21 kevin Exp $ +** $Id: projections.cpp,v 1.15 2000/07/15 08:36:13 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 @@ -486,7 +486,7 @@ Projections::printScanInfo (void) const */ bool -Projections::reconstruct (ImageFile& im, const char* const filterName, double filt_param, const char* const filterMethodName, const int zeropad, const char* const interpName, int interpFactor, const char* const backprojectName, const int trace) +Projections::reconstruct (ImageFile& im, const char* const filterName, double filt_param, const char* const filterMethodName, const int zeropad, const char* const interpName, int interpFactor, const char* const backprojectName, const int trace) const { double detInc = m_detInc; int n_filteredProj = m_nDet * interpFactor; @@ -548,8 +548,8 @@ Projections::reconstruct (ImageFile& im, const char* const filterName, double fi if (trace >= TRACE_TEXT) printf ("Reconstructing view %d (last = %d)\n", iview, m_nView - 1); - DetectorArray& darray = getDetectorArray (iview); - DetectorValue* detval = darray.detValues(); + const DetectorArray& darray = getDetectorArray (iview); + const DetectorValue* detval = darray.detValues(); filter.filterSignal (detval, filteredProj); diff --git a/src/Makefile.am b/src/Makefile.am index 9929768..4e82008 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS=ctsim -ctsim_SOURCES=ctsim.cpp docs.cpp views.cpp +ctsim_SOURCES=ctsim.cpp docs.cpp views.cpp ctsim.h docs.h views.h ctsim_DEPENDENCIES=../libctgraphics/libctgraphics.a ../libctsupport/libctsupport.a ../libctsim/libctsim.a ../include/ct.h ctsim_LDADD=-L../libctgraphics -L../libctsupport -L../libctsim @wxlibs@ diff --git a/src/ctsim.cpp b/src/ctsim.cpp index 0f7bc4e..c7db0f0 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.4 2000/07/13 07:01:59 kevin Exp $ +** $Id: ctsim.cpp,v 1.5 2000/07/15 08:36:13 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 @@ -41,34 +41,62 @@ #endif #include "wx/docview.h" - +#include "ct.h" #include "ctsim.h" #include "docs.h" #include "views.h" +class CTSimApp* theApp = NULL; + +struct option CTSimApp::ctsimOptions[] = +{ + {"help", 0, 0, O_HELP}, + {0, 0, 0, 0} +}; + IMPLEMENT_APP(CTSimApp) CTSimApp::CTSimApp(void) : m_docManager(NULL), m_pFrame(NULL) { + theApp = this; } bool CTSimApp::OnInit(void) { + // process options + while (1) { + int c = getopt_long (argc, argv, "", ctsimOptions, NULL); + if (c == -1) + break; + + switch (c) { + case O_HELP: + case '?': + usage (argv[0]); + exit (0); + default: + usage (argv[0]); + exit (1); + } + } + m_docManager = new wxDocManager; (void) new wxDocTemplate (m_docManager, "ImageFile", "*.if", "", "if", "ImageFile doc", "ImageFile View", CLASSINFO(ImageFileDocument), CLASSINFO(ImageFileView)); (void) new wxDocTemplate (m_docManager, "ProjectionFile", "*.pj", "", "pj", "ProjectionFile doc", "ProjectionFile View", CLASSINFO(ProjectionFileDocument), CLASSINFO(ProjectionFileView)); + (void) new wxDocTemplate (m_docManager, "PhantomFile", "*.phm", "", "phm", "Phantom doc", "Phantom View", CLASSINFO(PhantomDocument), CLASSINFO(PhantomView)); + //// Create the main frame window m_pFrame = new MainFrame(m_docManager, (wxFrame *) NULL, -1, "CTSim", wxPoint(0, 0), wxSize(500, 400), wxDEFAULT_FRAME_STYLE); //// Make a menubar wxMenu *file_menu = new wxMenu; - // file_menu->Append(wxID_NEW, "&New..."); + file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "&Create Phantom..."); file_menu->Append(wxID_OPEN, "&Open..."); file_menu->AppendSeparator(); @@ -78,6 +106,8 @@ CTSimApp::OnInit(void) m_docManager->FileHistoryUseMenu(file_menu); 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; @@ -87,13 +117,28 @@ CTSimApp::OnInit(void) m_pFrame->SetMenuBar(menu_bar); + SetTopWindow (m_pFrame); m_pFrame->Centre(wxBOTH); + m_pFrame->Show(true); - - SetTopWindow (m_pFrame); + + 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) +{ + cout << "usage: " << fileBasename(program) << " [files-to-open...] [OPTIONS]\n"; + cout << "Computed Tomography Simulator (Graphical Shell)\n"; + cout << "\n"; + cout << " --help Display this help message\n"; +} + int CTSimApp::OnExit(void) { @@ -101,26 +146,76 @@ CTSimApp::OnExit(void) return 0; } +wxString +CTSimApp::getUntitledFilename(void) +{ + static int untitledNumber = 1; + + wxString filename ("Untitled"); + filename << untitledNumber++; + + return (filename); +} + // Top-level window for CTSim IMPLEMENT_CLASS(MainFrame, wxDocParentFrame) + BEGIN_EVENT_TABLE(MainFrame, wxDocParentFrame) - EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout) - EVT_MENU(MAINMENU_FILE_EXIT, MainFrame::OnExit) + 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_EXIT, MainFrame::OnExit) 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) + : wxDocParentFrame(manager, frame, id, title, pos, size, type), m_pLog(NULL) { CreateStatusBar(); + 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)); SetStatusText ("Welcome to CTSim"); } void MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) { - wxMessageBox("CTSim\nAuthor: Kevin Rosenberg \nUsage: ctsim", "About CTSim", wxOK | wxICON_INFORMATION, this); + wxMessageBox("CTSim\nAuthor: Kevin Rosenberg \nUsage: ctsim [files-to-open..] [--help]", "About CTSim", wxOK | wxICON_INFORMATION, this); +} + +void +MainFrame::OnCreatePhantom(wxCommandEvent& WXUNUSED(event)) +{ + wxString choiceStringList [5]; + choiceStringList[0] = Phantom::PHM_HERMAN_STR; + choiceStringList[1] = Phantom::PHM_BHERMAN_STR; + choiceStringList[2] = Phantom::PHM_ROWLAND_STR;; + choiceStringList[3] = Phantom::PHM_BROWLAND_STR; + choiceStringList[4] = Phantom::PHM_UNITPULSE_STR; + wxString choiceTitleList [5]; + choiceTitleList[0] = "Herman Head"; + choiceTitleList[1] = "Herman Head Bordered"; + choiceTitleList[2] = "Rowland Head"; + choiceTitleList[3] = "Rowland Head Bordered"; + choiceTitleList[4] = "Unit Pulse"; + wxSingleChoiceDialog dialog (this, "Select phantom", "Phantom Selection", 5, choiceTitleList, NULL, wxOK|wxCANCEL|wxCENTRE); + + int dialogReturn = dialog.ShowModal(); + if (dialogReturn == wxID_OK) { + int selection = dialog.GetSelection(); + *theApp->getLog() << "Selected phantom " << selection << "\n"; + wxString filename = choiceStringList[selection] + ".phm"; + theApp->getDocManager()->CreateDocument(filename, wxDOC_SILENT); + } + +} + +void +MainFrame::OnHelpContents(wxCommandEvent& WXUNUSED(event) ) +{ + wxMessageBox("No help available, refer to man pages of command-line tools"); } void diff --git a/src/ctsim.h b/src/ctsim.h index db4d7c3..bbba38e 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.1 2000/07/13 07:01:59 kevin Exp $ +** $Id: ctsim.h,v 1.2 2000/07/15 08:36:13 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 @@ -30,8 +30,28 @@ #include "wx/docview.h" +// Define a new frame +class MainFrame: public wxDocParentFrame +{ + DECLARE_CLASS(MainFrame) +private: + wxTextCtrl* m_pLog; + +public: + MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type); + + void OnAbout (wxCommandEvent& event); + void OnHelpContents (wxCommandEvent& event); + void OnCreatePhantom (wxCommandEvent& event); + void OnExit (wxCommandEvent& event); + + wxTextCtrl* getLog() + { return m_pLog; } + + DECLARE_EVENT_TABLE() +}; + class wxDocManager; -class MainFrame; class CTSimApp: public wxApp { public: @@ -40,37 +60,41 @@ public: int OnExit(void); MainFrame* getMainFrame(void) const { return m_pFrame; } + wxTextCtrl* getLog(void) + { return m_pFrame->getLog(); } + wxDocManager* getDocManager() + { return m_docManager; } + + wxString getUntitledFilename(void); -protected: +private: wxDocManager* m_docManager; MainFrame* m_pFrame; -}; -DECLARE_APP(CTSimApp) + void usage (const char* program); -// Define a new frame -class MainFrame: public wxDocParentFrame -{ - DECLARE_CLASS(MainFrame) + static struct option ctsimOptions[]; -public: - MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type); - - void OnAbout (wxCommandEvent& event); - void OnExit (wxCommandEvent& event); - - DECLARE_EVENT_TABLE() + enum { O_HELP }; }; -extern MainFrame *GetMainFrame(void); +DECLARE_APP(CTSimApp) + +extern class CTSimApp* theApp; enum { MAINMENU_HELP_ABOUT = 500, + MAINMENU_HELP_CONTENTS, + MAINMENU_FILE_CREATE_PHANTOM, MAINMENU_FILE_EXIT, IFMENU_FILE_PROPERTIES, PJMENU_FILE_PROPERTIES, - PJMENU_FILE_RECONSTRUCT, + PHMMENU_FILE_PROPERTIES, + PJMENU_PROCESS_RECONSTRUCT, + IFMENU_VIEW_WINDOW_AUTO, + PHMMENU_PROCESS_RASTERIZE, + PHMMENU_PROCESS_PROJECTIONS, }; #endif diff --git a/src/docs.cpp b/src/docs.cpp index d5abb54..c39b72b 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.1 2000/07/13 07:01:59 kevin Exp $ +** $Id: docs.cpp,v 1.2 2000/07/15 08:36:13 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,37 +40,49 @@ #include "wx/wx.h" #endif #include "wx/txtstrm.h" +#include "wx/file.h" #if !wxUSE_DOC_VIEW_ARCHITECTURE #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h! #endif +#include "ct.h" +#include "ctsim.h" #include "docs.h" #include "views.h" - // ImageFileDocument IMPLEMENT_DYNAMIC_CLASS(ImageFileDocument, wxDocument) bool ImageFileDocument::OnSaveDocument(const wxString& filename) { - if (!m_imageFile.fileWrite (filename)) - return false; - Modify(false); - return true; + if (! m_imageFile.fileWrite (filename)) { + *theApp->getLog() << "Unable to write image file " << filename << "\n"; + return false; + } + *theApp->getLog() << "Wrote image file " << filename << "\n"; + Modify(false); + return true; } bool ImageFileDocument::OnOpenDocument(const wxString& filename) { - if (! m_imageFile.fileRead (filename)) - return false; - + if (filename == "untitled.if") { + wxString untitledFilename = theApp->getUntitledFilename(); + SetFilename (untitledFilename, true); + } else { + if (! m_imageFile.fileRead (filename)) { + *theApp->getLog() << "Unable to read image file " << filename << "\n"; + return false; + } + *theApp->getLog() << "Read image file " << filename << "\n"; SetFilename(filename, true); - Modify(false); - UpdateAllViews(); - return true; + } + Modify(false); + UpdateAllViews(); + return true; } bool ImageFileDocument::IsModified(void) const @@ -89,21 +101,31 @@ IMPLEMENT_DYNAMIC_CLASS(ProjectionFileDocument, wxDocument) bool ProjectionFileDocument::OnSaveDocument(const wxString& filename) { - if (!m_projectionFile.write (filename)) - return false; - Modify(false); - return true; + if (! m_projectionFile.write (filename)) { + *theApp->getLog() << "Unable to write projection file " << filename << "\n"; + return false; + } + *theApp->getLog() << "Wrote projection file " << filename << "\n"; + Modify(false); + return true; } bool ProjectionFileDocument::OnOpenDocument(const wxString& filename) { - if (! m_projectionFile.read (filename)) - return false; - + if (filename == "untitled.pj") { + wxString untitledFilename = theApp->getUntitledFilename(); + SetFilename (untitledFilename, true); + } else { + if (! m_projectionFile.read (filename)) { + *theApp->getLog() << "Unable to read projection file " << filename << "\n"; + return false; + } + *theApp->getLog() << "Read projection file " << filename << "\n"; SetFilename(filename, true); - Modify(false); - UpdateAllViews(); - return true; + } + Modify(false); + UpdateAllViews(); + return true; } bool ProjectionFileDocument::IsModified(void) const @@ -115,3 +137,40 @@ void ProjectionFileDocument::Modify(bool mod) { wxDocument::Modify(mod); } + + +// PhantomDocument + +IMPLEMENT_DYNAMIC_CLASS(PhantomDocument, wxDocument) + +bool PhantomDocument::OnOpenDocument(const wxString& filename) +{ + wxString myFilename = filename; + if (wxFile::Exists (myFilename)) { + m_phantom.createFromFile (myFilename); + } else { + myFilename.Replace (".phm", ""); + m_phantom.createFromPhantom (myFilename); + } + m_namePhantom = myFilename; + SetFilename (myFilename, true); + if (m_phantom.fail()) { + *theApp->getLog() << "Failure creating phantom " << myFilename << "\n"; + return false; + } + m_idPhantom = m_phantom.id(); + Modify(false); + UpdateAllViews(); + return true; +} + +bool PhantomDocument::IsModified(void) const +{ + return wxDocument::IsModified(); +} + +void PhantomDocument::Modify(bool mod) +{ + wxDocument::Modify(mod); +} + diff --git a/src/docs.h b/src/docs.h index 1cd4c40..bf69f06 100644 --- a/src/docs.h +++ b/src/docs.h @@ -1,7 +1,7 @@ /***************************************************************************** ** FILE IDENTIFICATION ** -** Name: doc.h +** Name: docs.h ** Purpose: Header file for Document routines of CTSim program ** Programmer: Kevin Rosenberg ** Date Started: July 2000 @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: docs.h,v 1.1 2000/07/13 07:01:59 kevin Exp $ +** $Id: docs.h,v 1.2 2000/07/15 08:36:13 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 @@ -44,13 +44,13 @@ private: ImageFile m_imageFile; public: - virtual bool OnSaveDocument(const wxString& filename); - virtual bool OnOpenDocument(const wxString& filename); - virtual bool IsModified(void) const; - virtual void Modify(bool mod); + virtual bool OnSaveDocument (const wxString& filename); + virtual bool OnOpenDocument (const wxString& filename); + virtual bool IsModified (void) const; + virtual void Modify (bool mod); - ImageFileDocument(void) {} - ~ImageFileDocument(void) {} + ImageFileDocument (void) {} + ~ImageFileDocument (void) {} const ImageFile& getImageFile(void) const { return m_imageFile; } @@ -67,33 +67,54 @@ private: Projections m_projectionFile; public: - virtual bool OnSaveDocument(const wxString& filename); - virtual bool OnOpenDocument(const wxString& filename); - virtual bool IsModified(void) const; - virtual void Modify(bool mod); + virtual bool OnSaveDocument (const wxString& filename); + virtual bool OnOpenDocument (const wxString& filename); + virtual bool IsModified (void) const; + virtual void Modify (bool mod); - ProjectionFileDocument(void) {} - ~ProjectionFileDocument(void) {} + ProjectionFileDocument (void) {} + ~ProjectionFileDocument (void) {} - const Projections& getProjections(void) const + const Projections& getProjections (void) const { return m_projectionFile; } - Projections& getProjections(void) + Projections& getProjections (void) { return m_projectionFile; } }; -class TextEditDocument: public wxDocument + +class PhantomDocument: public wxDocument { - DECLARE_DYNAMIC_CLASS(TextEditDocument) + DECLARE_DYNAMIC_CLASS(PhantomDocument) + private: + Phantom m_phantom; + Phantom::PhantomID m_idPhantom; + wxString m_namePhantom; + public: - virtual bool OnSaveDocument(const wxString& filename); - virtual bool OnOpenDocument(const wxString& filename); - virtual bool IsModified(void) const; - virtual void Modify(bool mod); - - TextEditDocument(void) {} - ~TextEditDocument(void) {} + PhantomDocument (void) + : m_idPhantom(Phantom::PHM_INVALID) + {} + + ~PhantomDocument (void) + {} + + const Phantom::PhantomID getPhantomID (void) const + { return m_idPhantom; } + + const wxString& getPhantomName (void) const + { return m_namePhantom; } + + const Phantom& getPhantom (void) const + { return m_phantom; } + + Phantom& getPhantom (void) + { return m_phantom; } + + virtual bool OnOpenDocument (const wxString& filename); + virtual bool IsModified (void) const; + virtual void Modify (bool mod); }; diff --git a/src/views.cpp b/src/views.cpp index 8a555ce..21fc80a 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.1 2000/07/13 07:01:59 kevin Exp $ +** $Id: views.cpp,v 1.2 2000/07/15 08:36:13 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 @@ -44,15 +44,14 @@ #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h! #endif +#include "wx/image.h" + +#include "ct.h" #include "ctsim.h" #include "docs.h" #include "views.h" #include #include "ct.h" -//#include "imagefile.h" -//#include "phantom.h" -//#include "scanner.h" -//#include "projections.h" // ImageFileCanvas @@ -83,12 +82,22 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event) wxClientDC dc(this); PrepareDC(dc); - dc.SetPen(*wxBLACK_PEN); - wxPoint pt(event.GetLogicalPosition(dc)); - if (event.LeftUp()) - cout << pt.x << "x" << pt.y << endl; + if (event.LeftUp()) { + const ImageFile& rIF = m_pView->GetDocument()->getImageFile(); + ImageFileArrayConst v = rIF.getArray(); + int nx = rIF.nx(); + int ny = rIF.ny(); + + if (pt.x >= 0 && pt.x < nx && pt.y >= 0 & pt.y < ny) { + ostringstream os; + os << "Image value (" << pt.x << "," << pt.y << ") = " << v[pt.x][pt.y] << "\n"; + *theApp->getLog() << os.str().c_str(); + } else + *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << pt.y << ")\n"; + + } } @@ -98,20 +107,12 @@ IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView) BEGIN_EVENT_TABLE(ImageFileView, wxView) EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties) + EVT_MENU(IFMENU_VIEW_WINDOW_AUTO, ImageFileView::OnWindowAuto) END_EVENT_TABLE() -bool ImageFileView::m_bPColoursInitialized = false; -wxColour* ImageFileView::m_pColours[256]; - ImageFileView::ImageFileView(void) : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false) { - if (! m_bPColoursInitialized) { - for (int i = 0; i < 256; i++) - m_pColours[i] = new wxColour (i, i, i); - - m_bPColoursInitialized = true; - } } ImageFileView::~ImageFileView(void) @@ -122,12 +123,27 @@ void ImageFileView::OnProperties (wxCommandEvent& event) { double min, max, mean, mode, median, stddev; - const ImageFile& rIF = dynamic_cast(GetDocument())->getImageFile(); - const string& rFilename = rIF.getFilename(); - rIF.statistics (min, max, mean, mode, median, stddev); - ostringstream os; - os << "file: " << rFilename << "\nmin: "<getImageFile(); + if (rIF.nx() == 0 || rIF.ny() == 0) + *theApp->getLog() << "Properties: empty imagefile\n"; + else { + const string& rFilename = rIF.getFilename(); + rIF.statistics (min, max, mean, mode, median, stddev); + ostringstream os; + os << "file: " << rFilename << "\nmin: "<getLog() << os.str().c_str(); + } +} + +void +ImageFileView::OnWindowAuto (wxCommandEvent& event) +{ + *theApp->getLog() << "ImageFile: Window Auto\n"; + m_minPixel = .2; + m_maxPixel = .22; + m_bMinSpecified = true; + m_bMaxSpecified = true; + OnUpdate(this, NULL); } @@ -150,11 +166,10 @@ ImageFileView::CreateCanvas (wxView *view, wxFrame *parent) wxFrame* ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) { - wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, dynamic_cast(wxTheApp)->getMainFrame(), -1, "ImageFile Frame", wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE); + wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "ImageFile Frame", wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE); wxMenu *file_menu = new wxMenu; - file_menu->Append(wxID_NEW, "&New..."); file_menu->Append(wxID_OPEN, "&Open..."); file_menu->Append(wxID_CLOSE, "&Close"); file_menu->Append(wxID_SAVE, "&Save"); @@ -168,12 +183,16 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view) file_menu->Append(wxID_PRINT_SETUP, "Print &Setup..."); file_menu->Append(wxID_PREVIEW, "Print Pre&view"); + wxMenu *view_menu = new wxMenu; + view_menu->Append(IFMENU_VIEW_WINDOW_AUTO, "&Window auto"); + wxMenu *help_menu = new wxMenu; help_menu->Append(MAINMENU_HELP_ABOUT, "&About"); wxMenuBar *menu_bar = new wxMenuBar; menu_bar->Append(file_menu, "&File"); + menu_bar->Append(view_menu, "&View"); menu_bar->Append(help_menu, "&Help"); subframe->SetMenuBar(menu_bar); @@ -212,8 +231,8 @@ ImageFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) void ImageFileView::OnDraw (wxDC* dc) { - const ImageFile& rIF = dynamic_cast(GetDocument())->getImageFile(); - dc->Blit(static_cast(0), static_cast(0), static_cast(rIF.nx()), static_cast(rIF.ny()), &m_memoryDC, static_cast(0), static_cast(0)); + if (m_bitmap.Ok()) + dc->DrawBitmap(m_bitmap, 0, 0, false); } @@ -235,27 +254,21 @@ ImageFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) } double scaleWidth = m_maxPixel - m_minPixel; - m_pBitmap = new wxBitmap (rIF.nx(), rIF.ny()); - m_memoryDC.SelectObject (*m_pBitmap); - m_memoryDC.BeginDrawing(); - - wxPen pen (*m_pColours[128], 1, wxDOT); - m_memoryDC.SetPen (pen); + unsigned char imageData [nx * ny * 3]; for (int ix = 0; ix < nx; ix++) { for (int iy = 0; iy < ny; iy++) { double scaleValue = ((v[ix][iy] - m_minPixel) / scaleWidth) * 255; int intensity = static_cast(scaleValue + 0.5); intensity = clamp (intensity, 0, 255); - pen.SetColour (*m_pColours[intensity]); - m_memoryDC.SetPen(pen); - m_memoryDC.DrawPoint(ix, ny - iy); + int baseAddr = ((ny - 1 - iy) * nx + ix) * 3; + imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity; } } + wxImage image (ny, nx, imageData, true); + m_bitmap = image.ConvertToBitmap(); } - m_memoryDC.EndDrawing(); if (m_canvas) { - // m_canvas->SetScrollbars (50, 50, nx / 50, ny / 50, 0, 0, false); m_canvas->Refresh(); } @@ -280,7 +293,7 @@ ImageFileView::OnClose (bool deleteWindow) m_canvas->Clear(); m_canvas->m_pView = NULL; m_canvas = NULL; - wxString s(wxTheApp->GetAppName()); + wxString s(theApp->GetAppName()); if (m_frame) m_frame->SetTitle(s); SetFrame(NULL); @@ -296,7 +309,205 @@ ImageFileView::OnClose (bool deleteWindow) -// ProjectionFileCanvas +// PhantomCanvas + +PhantomCanvas::PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style) + : wxScrolledWindow(frame, -1, pos, size, style) +{ + m_pView = v; +} + +void +PhantomCanvas::OnDraw(wxDC& dc) +{ + if (m_pView) + m_pView->OnDraw(& dc); +} + +// PhantomView + +IMPLEMENT_DYNAMIC_CLASS(PhantomView, wxView) + +BEGIN_EVENT_TABLE(PhantomView, wxView) + EVT_MENU(PHMMENU_FILE_PROPERTIES, PhantomView::OnProperties) + EVT_MENU(PHMMENU_PROCESS_RASTERIZE, PhantomView::OnRasterize) + EVT_MENU(PHMMENU_PROCESS_PROJECTIONS, PhantomView::OnProjections) +END_EVENT_TABLE() + +PhantomView::PhantomView(void) + : wxView(), m_canvas(NULL), m_frame(NULL) +{ +} + +PhantomView::~PhantomView(void) +{ +} + +void +PhantomView::OnProperties (wxCommandEvent& event) +{ + const Phantom::PhantomID idPhantom = GetDocument()->getPhantomID(); + const string& namePhantom = GetDocument()->getPhantomName(); + ostringstream os; + os << "Phantom " << namePhantom << " (" << static_cast(idPhantom) << ")\n"; + *theApp->getLog() << os.str().c_str(); + const Phantom& rPhantom = GetDocument()->getPhantom(); +#if DEBUG + rPhantom.print(); +#endif +} + + +void +PhantomView::OnProjections (wxCommandEvent& event) +{ +} + + +void +PhantomView::OnRasterize (wxCommandEvent& event) +{ + const Phantom& rPhantom = GetDocument()->getPhantom(); + ImageFileDocument* pRasterDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT)); + ImageFile& imageFile = pRasterDoc->getImageFile(); + imageFile.setArraySize (256, 256); + imageFile.arrayDataClear(); + rPhantom.convertToImagefile (imageFile, 1, TRACE_NONE); + pRasterDoc->Modify(true); + pRasterDoc->UpdateAllViews(this); +} + + +PhantomCanvas* +PhantomView::CreateCanvas (wxView *view, wxFrame *parent) +{ + PhantomCanvas* pCanvas; + int width, height; + parent->GetClientSize(&width, &height); + + pCanvas = new PhantomCanvas (dynamic_cast(view), parent, wxPoint(0, 0), wxSize(width, height), 0); + + pCanvas->SetScrollbars(20, 20, 50, 50); + pCanvas->SetBackgroundColour(*wxWHITE); + pCanvas->Clear(); + + return pCanvas; +} + +wxFrame* +PhantomView::CreateChildFrame(wxDocument *doc, wxView *view) +{ + wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Phantom Frame", wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE); + + wxMenu *file_menu = new wxMenu; + + file_menu->Append(wxID_OPEN, "&Open..."); + file_menu->Append(wxID_CLOSE, "&Close"); + + file_menu->AppendSeparator(); + file_menu->Append(PHMMENU_FILE_PROPERTIES, "P&roperties"); + + file_menu->AppendSeparator(); + file_menu->Append(wxID_PRINT, "&Print..."); + file_menu->Append(wxID_PRINT_SETUP, "Print &Setup..."); + file_menu->Append(wxID_PREVIEW, "Print Pre&view"); + + wxMenu *process_menu = new wxMenu; + process_menu->Append(PHMMENU_PROCESS_RASTERIZE, "&Rasterize..."); + process_menu->Append(PHMMENU_PROCESS_PROJECTIONS, "&Projections..."); + + wxMenu *help_menu = new wxMenu; + help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents"); + help_menu->Append(MAINMENU_HELP_ABOUT, "&About"); + + wxMenuBar *menu_bar = new wxMenuBar; + + menu_bar->Append(file_menu, "&File"); + menu_bar->Append(process_menu, "&Process"); + menu_bar->Append(help_menu, "&Help"); + + subframe->SetMenuBar(menu_bar); + + subframe->Centre(wxBOTH); + + return subframe; +} + + +bool +PhantomView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) +{ + m_frame = CreateChildFrame(doc, this); + + int width, height; + m_frame->GetClientSize(&width, &height); + m_frame->SetTitle("PhantomView"); + m_canvas = CreateCanvas(this, m_frame); + +#ifdef __X__ + int x, y; // X requires a forced resize + m_frame->GetSize(&x, &y); + m_frame->SetSize(-1, -1, x, y); +#endif + + m_frame->Show(true); + Activate(true); + + return true; +} + +void +PhantomView::OnDraw (wxDC* dc) +{ + // if (m_bitmap.Ok()) + // dc->DrawBitmap (m_bitmap, 0, 0, false); +} + + +void +PhantomView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) +{ + if (m_canvas) { + m_canvas->Refresh(); + } + +#ifdef __WXMSW__ + if (m_canvas) + m_canvas->Refresh(); +#else + if (m_canvas) { + wxClientDC dc(m_canvas); + dc.Clear(); + OnDraw (&dc); + } +#endif +} + +bool +PhantomView::OnClose (bool deleteWindow) +{ + if (!GetDocument()->Close()) + return false; + + m_canvas->Clear(); + m_canvas->m_pView = NULL; + m_canvas = NULL; + wxString s(wxTheApp->GetAppName()); + if (m_frame) + m_frame->SetTitle(s); + SetFrame(NULL); + + Activate(false); + + if (deleteWindow) { + delete m_frame; + return true; + } + return true; +} + + +// ProjectionCanvas ProjectionFileCanvas::ProjectionFileCanvas (ProjectionFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style) : wxScrolledWindow(frame, -1, pos, size, style) @@ -317,21 +528,12 @@ IMPLEMENT_DYNAMIC_CLASS(ProjectionFileView, wxView) BEGIN_EVENT_TABLE(ProjectionFileView, wxView) EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties) - EVT_MENU(PJMENU_FILE_RECONSTRUCT, ProjectionFileView::OnReconstruct) + EVT_MENU(PJMENU_PROCESS_RECONSTRUCT, ProjectionFileView::OnReconstruct) END_EVENT_TABLE() -bool ProjectionFileView::m_bPColoursInitialized = false; -wxColour* ProjectionFileView::m_pColours[256]; - ProjectionFileView::ProjectionFileView(void) : wxView(), m_canvas(NULL), m_frame(NULL) { - if (! m_bPColoursInitialized) { - for (int i = 0; i < 256; i++) - m_pColours[i] = new wxColour (i, i, i); - - m_bPColoursInitialized = true; - } } ProjectionFileView::~ProjectionFileView(void) @@ -341,22 +543,30 @@ ProjectionFileView::~ProjectionFileView(void) void ProjectionFileView::OnProperties (wxCommandEvent& event) { - const Projections& rProj = dynamic_cast(GetDocument())->getProjections(); - const string& rFilename = rProj.getFilename(); + const Projections& rProj = GetDocument()->getProjections(); ostringstream os; - os << "file: " << rFilename << "\nDetectors: " << rProj.nDet() << "\nViews: " << rProj.nView(); - wxMessageBox(os.str().c_str(), "Projection Properties", wxOK | wxICON_INFORMATION, m_frame); + os << "ProjectionFile " << rProj.getFilename() << ": Number of Detectors = " << rProj.nDet() << ", Number of Views = " << rProj.nView() << "\n"; + *theApp->getLog() << os.str().c_str(); } void ProjectionFileView::OnReconstruct (wxCommandEvent& event) { - const Projections& rProj = dynamic_cast(GetDocument())->getProjections(); - const string& rFilename = rProj.getFilename(); - ostringstream os; - os << "Reconstruct file " << rFilename; - wxMessageBox(os.str().c_str(), "Reconstruction Dialog", wxOK | wxICON_INFORMATION, m_frame); + ImageFileDocument* pReconDoc = dynamic_cast(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT)); + ImageFile& imageFile = pReconDoc->getImageFile(); + const Projections& rProj = GetDocument()->getProjections(); + string optFilterName = "abs_bandlimit"; + double optFilterParam = 1.; + string optFilterMethodName = "convolution"; + int optZeropad = 3; + string optInterpName = "linear"; + int optInterpParam = 1; + string optBackprojectName = "idiff3"; + imageFile.setArraySize (256, 256); + rProj.reconstruct (imageFile, optFilterName.c_str(), optFilterParam, optFilterMethodName.c_str(), optZeropad, optInterpName.c_str(), optInterpParam, optBackprojectName.c_str(), TRACE_NONE); + pReconDoc->Modify(true); + pReconDoc->UpdateAllViews(this); } @@ -379,18 +589,14 @@ ProjectionFileView::CreateCanvas (wxView *view, wxFrame *parent) wxFrame* ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) { - wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, dynamic_cast(wxTheApp)->getMainFrame(), -1, "ProjectionFile Frame", wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE); + wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Projection Frame", wxPoint(10, 10), wxSize(300, 300), wxDEFAULT_FRAME_STYLE); wxMenu *file_menu = new wxMenu; - file_menu->Append(wxID_NEW, "&New..."); file_menu->Append(wxID_OPEN, "&Open..."); file_menu->Append(wxID_CLOSE, "&Close"); - file_menu->Append(wxID_SAVE, "&Save"); - file_menu->Append(wxID_SAVEAS, "Save &As..."); file_menu->AppendSeparator(); - file_menu->Append(PJMENU_FILE_RECONSTRUCT, "R&econstuct"); file_menu->Append(PJMENU_FILE_PROPERTIES, "P&roperties"); file_menu->AppendSeparator(); @@ -398,12 +604,18 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view) file_menu->Append(wxID_PRINT_SETUP, "Print &Setup..."); file_menu->Append(wxID_PREVIEW, "Print Pre&view"); + wxMenu *process_menu = new wxMenu; + process_menu->Append(PJMENU_PROCESS_RECONSTRUCT, "R&econstruct..."); + 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(process_menu, "&Process"); menu_bar->Append(help_menu, "&Help"); subframe->SetMenuBar(menu_bar); @@ -439,23 +651,25 @@ ProjectionFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) void ProjectionFileView::OnDraw (wxDC* dc) { - const Projections& rProj = dynamic_cast(GetDocument())->getProjections(); - dc->Blit(static_cast(0), static_cast(0), static_cast(rProj.nDet()), static_cast(rProj.nView()), &m_memoryDC, static_cast(0), static_cast(0)); + if (m_bitmap.Ok()) + dc->DrawBitmap (m_bitmap, 0, 0, false); } void ProjectionFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) ) { - const Projections& rProj = dynamic_cast(GetDocument())->getProjections(); - const DetectorArray& detarray = rProj.getDetectorArray (0); + const Projections& rProj = GetDocument()->getProjections(); + const int nDet = rProj.nDet(); + const int nView = rProj.nView(); + const DetectorArray& detarray = rProj.getDetectorArray(0); const DetectorValue* detval = detarray.detValues(); double min = detval[0]; double max = detval[0]; - for (int iy = 0; iy < rProj.nView(); iy++) { - const DetectorArray& detarray = rProj.getDetectorArray (iy); - detval = detarray.detValues(); - for (int ix = 0; ix < rProj.nDet(); ix++) { + for (int iy = 0; iy < nView; iy++) { + const DetectorArray& detarray = rProj.getDetectorArray(iy); + const DetectorValue* detval = detarray.detValues(); + for (int ix = 0; ix < nDet; ix++) { if (min > detval[ix]) min = detval[ix]; else if (max < detval[ix]) @@ -463,30 +677,22 @@ ProjectionFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) } } - double scaleWidth = max - min; - - m_pBitmap = new wxBitmap (rProj.nDet(), rProj.nView()); - m_memoryDC.SelectObject (*m_pBitmap); - m_memoryDC.BeginDrawing(); - - wxPen pen (*m_pColours[128], 1, wxDOT); - m_memoryDC.SetPen (pen); - for (int iy = 0; iy < rProj.nView(); iy++) { - const DetectorArray& detarray = rProj.getDetectorArray (iy); - detval = detarray.detValues(); - for (int ix = 0; ix < rProj.nDet(); ix++) { - double scaleValue = ((detval[ix] - min) / scaleWidth) * 255; - int intensity = static_cast(scaleValue + 0.5); - intensity = clamp (intensity, 0, 255); - pen.SetColour (*m_pColours[intensity]); - m_memoryDC.SetPen(pen); - m_memoryDC.DrawPoint(ix, iy); + unsigned char imageData [nDet * nView * 3]; + double scale = (max - min) / 255; + for (int iy = 0; iy < nView; iy++) { + const DetectorArray& detarray = rProj.getDetectorArray(iy); + const DetectorValue* detval = detarray.detValues(); + for (int ix = 0; ix < nDet; ix++) { + int intensity = static_cast(((detval[ix] - min) / scale) + 0.5); + intensity = clamp(intensity, 0, 255); + int baseAddr = (iy * nDet + ix) * 3; + imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity; } } - m_memoryDC.EndDrawing(); - + wxImage image (nDet, nView, imageData, true); + m_bitmap = image.ConvertToBitmap(); + if (m_canvas) { - // m_canvas->SetScrollbars (50, 50, nx / 50, ny / 50, 0, 0, false); m_canvas->Refresh(); } diff --git a/src/views.h b/src/views.h index 4e833bb..ee3fdda 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.1 2000/07/13 07:01:59 kevin Exp $ +** $Id: views.h,v 1.2 2000/07/15 08:36:13 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 @@ -33,6 +33,7 @@ #define __VIEWSH__ #include "wx/wx.h" +#include "docs.h" #include "imagefile.h" class ImageFileCanvas; @@ -41,7 +42,7 @@ class ImageFileView : public wxView DECLARE_DYNAMIC_CLASS(ImageFileView) wxMemoryDC m_memoryDC; - wxBitmap* m_pBitmap; + wxBitmap m_bitmap; private: ImageFileCanvas *CreateCanvas(wxView *view, wxFrame *parent); @@ -54,9 +55,6 @@ private: double m_minPixel; double m_maxPixel; - static bool m_bPColoursInitialized; - static wxColour* m_pColours[256]; - public: ImageFileView(void); ~ImageFileView(void); @@ -66,6 +64,10 @@ public: void OnUpdate(wxView *sender, wxObject *hint = NULL); bool OnClose (bool deleteWindow = true); void OnProperties (wxCommandEvent& event); + void OnWindowAuto (wxCommandEvent& event); + + ImageFileDocument* GetDocument(void) + { return dynamic_cast(wxView::GetDocument()); } DECLARE_EVENT_TABLE() }; @@ -83,41 +85,13 @@ public: }; -class MyTextWindow: public wxTextCtrl -{ -public: - wxView *m_pView; - - MyTextWindow(wxView *v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style); -}; - - -class TextEditView: public wxView -{ - DECLARE_DYNAMIC_CLASS(TextEditView) -private: - wxFrame *CreateChildFrame(wxDocument *doc, wxView *view); - -public: - wxFrame *frame; - MyTextWindow *textsw; - - TextEditView(): wxView() { frame = (wxFrame *) NULL; textsw = (MyTextWindow *) NULL; } - ~TextEditView(void) {} - - bool OnCreate(wxDocument *doc, long flags); - void OnDraw(wxDC* dc); - void OnUpdate(wxView *sender, wxObject *hint = (wxObject *) NULL); - bool OnClose(bool deleteWindow = TRUE); -}; - class ProjectionFileCanvas; class ProjectionFileView : public wxView { DECLARE_DYNAMIC_CLASS(ProjectionFileView) wxMemoryDC m_memoryDC; - wxBitmap* m_pBitmap; + wxBitmap m_bitmap; private: ProjectionFileCanvas *CreateCanvas(wxView *view, wxFrame *parent); @@ -126,9 +100,6 @@ private: ProjectionFileCanvas *m_canvas; wxFrame *m_frame; - static bool m_bPColoursInitialized; - static wxColour* m_pColours[256]; - public: ProjectionFileView(void); ~ProjectionFileView(void); @@ -140,6 +111,8 @@ public: void OnProperties (wxCommandEvent& event); void OnReconstruct (wxCommandEvent& event); + ProjectionFileDocument* GetDocument(void) + { return dynamic_cast(wxView::GetDocument()); } DECLARE_EVENT_TABLE() }; @@ -153,4 +126,46 @@ public: }; +class PhantomCanvas; +class PhantomView : public wxView +{ + DECLARE_DYNAMIC_CLASS(PhantomView) + +private: + PhantomCanvas *CreateCanvas(wxView *view, wxFrame *parent); + wxFrame *CreateChildFrame(wxDocument *doc, wxView *view); + + PhantomCanvas *m_canvas; + wxFrame *m_frame; + +public: + PhantomView(void); + ~PhantomView(void); + + bool OnCreate(wxDocument *doc, long flags); + void OnDraw(wxDC* dc); + void OnUpdate(wxView *sender, wxObject *hint = NULL); + bool OnClose (bool deleteWindow = true); + void OnProperties (wxCommandEvent& event); + void OnRasterize (wxCommandEvent& event); + void OnProjections (wxCommandEvent& event); + + PhantomDocument* GetDocument(void) + { return dynamic_cast(wxView::GetDocument()); } + + DECLARE_EVENT_TABLE() +}; + +class PhantomCanvas: public wxScrolledWindow +{ +public: + PhantomView* m_pView; + + PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style); + virtual void OnDraw(wxDC& dc); + +}; + + #endif + diff --git a/tools/pjrec.cpp b/tools/pjrec.cpp index dc00484..df9af1c 100644 --- a/tools/pjrec.cpp +++ b/tools/pjrec.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2000 Kevin Rosenberg ** -** $Id: pjrec.cpp,v 1.1 2000/07/13 07:01:35 kevin Exp $ +** $Id: pjrec.cpp,v 1.2 2000/07/15 08:36:13 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 @@ -135,7 +135,6 @@ pjrec_main (int argc, char * argv[]) string optFilterMethodName = SignalFilter::FILTER_METHOD_CONVOLUTION_STR; string optInterpName = Backprojector::INTERP_LINEAR_STR; string optBackprojName = Backprojector::BPROJ_IDIFF2_STR; - // string optFilterMethodName = SignalFilter::FILTER_METHOD_CONVOLUTION_STR; int optPreinterpolationFactor = 1; int nx, ny; #ifdef HAVE_MPI