/*=============================================================================
Project: SharpImage
Module: siFormMain.cs
Language: C#
Author: Dan Mueller
Date: $Date: 2008-01-09 16:23:10 +1000 (Wed, 09 Jan 2008) $
Revision: $Revision: 29 $
Copyright (c) Queensland University of Technology (QUT) 2007.
All rights reserved.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=============================================================================*/
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Threading;
using IronPython.Hosting;
using Crownwood.Magic.Common;
using Crownwood.Magic.Controls;
using SharpImage.Main;
using SharpImage.Script;
using SharpImage.Forms;
using SharpImage.Properties;
using SharpImage.Rendering;
namespace SharpImage.Main
{
public partial class siFormMain : Form, IApplication
{
#region ImageParams and ImageSeriesParams Struct
//=====================================================================
private class ImageParams
{
private itk.itkImageBase m_Image;
private String m_FullPath;
private bool m_Compress;
private bool m_Sucess;
private Exception m_Exception;
public ImageParams(itk.itkImageBase image, String fullPath)
{
this.m_Image = image;
this.m_FullPath = fullPath;
this.m_Compress = false;
this.m_Sucess = false;
this.m_Exception = null;
}
public ImageParams(itk.itkImageBase image, String fullPath, bool compress)
{
this.m_Image = image;
this.m_FullPath = fullPath;
this.m_Compress = compress;
this.m_Sucess = false;
this.m_Exception = null;
}
public itk.itkImageBase Image
{
get { return this.m_Image; }
}
public String FullPath
{
get { return this.m_FullPath; }
}
public bool Compress
{
get { return this.m_Compress; }
set { this.m_Compress = value; }
}
public bool Success
{
get { return this.m_Sucess; }
set { this.m_Sucess = value; }
}
public Exception Exception
{
get { return this.m_Exception; }
set { this.m_Exception = value; }
}
}
private class ImageSeriesParams
{
private itk.itkImageBase m_Image;
private String[] m_Files;
private bool m_Sucess;
private Exception m_Exception;
public ImageSeriesParams(itk.itkImageBase image, String[] files)
{
this.m_Image = image;
this.m_Files = files;
this.m_Sucess = false;
this.m_Exception = null;
}
public itk.itkImageBase Image
{
get { return this.m_Image; }
}
public String[] Files
{
get { return this.m_Files; }
}
public bool Success
{
get { return this.m_Sucess; }
set { this.m_Sucess = value; }
}
public Exception Exception
{
get { return this.m_Exception; }
set { this.m_Exception = value; }
}
}
//=====================================================================
#endregion
#region ExecuteScriptParams Struct
//=====================================================================
private struct ExecuteScriptParams
{
private PythonEngine m_Engine;
private string m_FullPath;
public ExecuteScriptParams(PythonEngine engine, string fullPath)
{
this.m_Engine = engine;
this.m_FullPath = fullPath;
}
public PythonEngine Engine
{
get { return this.m_Engine; }
}
public string FullPath
{
get { return this.m_FullPath; }
}
}
//=====================================================================
#endregion
#region Constants
//=====================================================================
private const string STATUS_READY = "Ready...";
private const string APPLICATION_TEXT = "SharpImage" + " [" + siVersion.VERSION + "]";
//=====================================================================
#endregion
#region FormMain Methods
//=====================================================================
///
/// Default constructor.
///
public siFormMain()
{
InitializeComponent();
// Setup FormMain
this.Text = APPLICATION_TEXT;
this.Size = new Size(800, 700);
this.MenuScriptConsole_Click(this, new EventArgs());
this.HideTabBottom();
this.HideTabRight();
this.SetApplicationAsReady(0);
// Watch the tabs collection
this.tabBottom.TabPages.Cleared += new Crownwood.Magic.Collections.CollectionClear(TabBottom_TabPages_Cleared);
this.tabBottom.TabPages.Removed += new Crownwood.Magic.Collections.CollectionChange(TabPages_Removed);
this.tabRight.TabPages.Cleared += new Crownwood.Magic.Collections.CollectionClear(TabRight_TabPages_Cleared);
this.tabRight.TabPages.Removed += new Crownwood.Magic.Collections.CollectionChange(TabPages_Removed);
// Watch the script console for commands
this.ScriptConsole.UserEnteredScriptCommand += new siFormScriptConsole.ScriptCommandHandler(ScriptConsole_UserEnteredScriptCommand);
// Add support for recently opened images
this.m_RecentOpenImage = new siRecentFileManager("SharpImage", "RecentOpenImage");
this.RefreshRecentOpenImageMenu();
// Add support for recently executed scripts
this.m_RecentExecuteScripts = new siRecentFileManager("SharpImage", "RecentExecuteScript");
this.RefreshRecentExecuteScriptsMenu();
// Add a form closing handler to persist entries to registry
this.FormClosing += new FormClosingEventHandler(FormMain_FormClosing);
}
void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
// Hide the form so it doesn't look unresponsive while
// we persist recent files
this.Hide();
// Finish up
this.ExitApplication();
}
void TabPages_Removed(int index, object value)
{
if (this.tabBottom.TabPages.Count == 0)
this.HideTabBottom();
if (this.tabRight.TabPages.Count == 0)
this.HideTabRight();
}
private void TabBottom_ClosePressed(object sender, EventArgs e)
{
if (this.tabBottom.SelectedTab != null)
this.tabBottom.TabPages.Remove(this.tabBottom.SelectedTab);
}
private void TabRight_ClosePressed(object sender, EventArgs e)
{
if (this.tabRight.SelectedTab != null)
{
// Try to close the form associated with the page
if (this.tabRight.SelectedTab.Tag != null &&
this.tabRight.SelectedTab.Tag is Form)
// NOTE: IApplication.AddToolForm is watching the FormClosed
// event and will remove the tab
(this.tabRight.SelectedTab.Tag as Form).Close();
else
// Remove the page
this.tabRight.TabPages.Remove(this.tabRight.SelectedTab);
}
}
void TabBottom_TabPages_Cleared()
{
this.HideTabBottom();
}
void TabRight_TabPages_Cleared()
{
this.HideTabRight();
}
private void ShowTabBottom()
{
this.splitterBottom.Visible = true;
this.tabBottom.Visible = true;
}
private void ShowTabRight()
{
this.splitterRight.Visible = true;
this.tabRight.Visible = true;
}
private void HideTabBottom()
{
this.splitterBottom.Visible = false;
this.tabBottom.Visible = false;
}
private void HideTabRight()
{
this.tabRight.Visible = false;
this.splitterRight.Visible = false;
}
private void MenuWindowCascade_Click(object sender, EventArgs e)
{
this.LayoutMdi(MdiLayout.Cascade);
}
private void MenuWindowTileV_Click(object sender, EventArgs e)
{
this.LayoutMdi(MdiLayout.TileVertical);
}
private void MenuWindowTileH_Click(object sender, EventArgs e)
{
this.LayoutMdi(MdiLayout.TileHorizontal);
}
private void MenuWindowArrangeIcons_Click(object sender, EventArgs e)
{
this.LayoutMdi(MdiLayout.ArrangeIcons);
}
private void menuWindowHideUnused_Click(object sender, EventArgs e)
{
foreach (siRenderer renderer in this.Renderers)
if (renderer.Form != this.ActiveMdiChild)
renderer.Hide();
}
private void menuWindowShowAll_Click(object sender, EventArgs e)
{
foreach (siRenderer renderer in this.Renderers)
renderer.Form.Show();
}
//=====================================================================
#endregion
#region IApplication Implemenation
//=====================================================================
#region IApplication Thread-safe Delegates
//=====================================================================
delegate void IApplicationShowMessageCallback1(string text);
delegate void IApplicationShowMessageCallback2(string text, string caption);
delegate void IApplicationShowMessageCallback3(string text, string caption, MessageBoxButtons buttons);
delegate void IApplicationShowMessageCallback4(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon);
delegate void IApplicationSetAsWorkingCallback();
delegate void IApplicationSetProgressCallback(int progress);
delegate void IApplicationSetStatusLabelCallback(string status);
delegate void IApplicationSetAsReadyCallback(int pause);
delegate void IApplicationRendererCallback(siRenderer renderer);
delegate siRenderer IApplicationImageCallback(itk.itkImageBase image);
delegate void IApplicationAddToolCallback(siFormTool form);
delegate itk.itkImageBase IApplicationOpenImageCallback2(bool display, string title);
delegate itk.itkImageBase IApplicationOpenImageCallback4(bool display, string title, itk.itkPixelType pixeltype, int dim);
//=====================================================================
#endregion
#region IApplication Properties
//=====================================================================
private Dictionary m_Metadata = new Dictionary();
public Dictionary Metadata
{
get { return this.m_Metadata; }
}
private siFormScriptConsole m_ScriptConsole = null;
public siFormScriptConsole ScriptConsole
{
get
{
if (this.m_ScriptConsole == null)
this.m_ScriptConsole = new siFormScriptConsole(this);
return this.m_ScriptConsole;
}
}
public siRenderer CurrentRenderer
{
get
{
foreach (siRenderer renderer in this.Renderers)
if (this.ActiveMdiChild == renderer.Form)
return renderer;
if (this.Renderers.Count > 0)
return this.Renderers[0];
else
return null;
}
}
private List m_Renderers = new List();
public List Renderers
{
get { return this.m_Renderers; }
}
//=====================================================================
#endregion
#region IApplication Methods
//=====================================================================
///
/// Invoke the given delegate on the application thread.
///
///
///
public object InvokeArg0(Delegate method)
{
return this.Invoke(method);
}
///
/// Invoke the given delegate on the application thread.
///
///
///
///
public object InvokeArg1(Delegate method, object arg1)
{
return this.Invoke(method, arg1);
}
///
/// Invoke the given delegate on the application thread.
///
///
///
///
///
public object InvokeArg2(Delegate method, object arg1, object arg2)
{
return this.Invoke(method, arg1, arg2);
}
///
/// Invoke the given delegate on the application thread.
///
///
///
///
///
///
public object InvokeArg3(Delegate method, object arg1, object arg2, object arg3)
{
return this.Invoke(method, arg1, arg2, arg3);
}
///
/// Invoke the given delegate on the application thread.
///
///
///
///
///
///
///
public object InvokeArg4(Delegate method, object arg1, object arg2, object arg3, object arg4)
{
return this.Invoke(method, arg1, arg2, arg3, arg4);
}
///
/// A thread-safe method for showing a message box owned by
/// the main IApplication window.
///
/// This method is thread-safe.
///
public void ShowMessageBox(string text)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
IApplicationShowMessageCallback1 d = new IApplicationShowMessageCallback1(this.ShowMessageBox);
this.Invoke(d, text);
return;
}
// Show the message
MessageBox.Show(this, text);
}
///
/// A thread-safe method for showing a message box owned by
/// the main IApplication window.
///
/// This method is thread-safe.
///
///
public void ShowMessageBox(string text, string caption)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
IApplicationShowMessageCallback2 d = new IApplicationShowMessageCallback2(this.ShowMessageBox);
this.Invoke(d, text, caption);
return;
}
// Show the message
MessageBox.Show(this, text, caption);
}
///
/// A thread-safe method for showing a message box owned by
/// the main IApplication window.
///
/// This method is thread-safe.
///
///
///
public void ShowMessageBox(string text, string caption, MessageBoxButtons buttons)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
IApplicationShowMessageCallback3 d = new IApplicationShowMessageCallback3(this.ShowMessageBox);
this.Invoke(d, text, caption, buttons);
return;
}
// Show the message
MessageBox.Show(this, text, caption, buttons);
}
///
/// A thread-safe method for showing a message box owned by
/// the main IApplication window.
///
/// This method is thread-safe.
///
///
///
///
public void ShowMessageBox(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
IApplicationShowMessageCallback4 d = new IApplicationShowMessageCallback4(this.ShowMessageBox);
this.Invoke(d, text, caption, buttons, icon);
return;
}
// Show the message
MessageBox.Show(this, text, caption, buttons, icon);
}
///
/// A thread-safe method for setting the application as working.
/// This method sets the cursor.
///
/// This method is thread-safe.
public void SetApplicationAsWorking()
{
// Make the call thread-safe
if (this.InvokeRequired)
{
this.Invoke(new IApplicationSetAsWorkingCallback(this.SetApplicationAsWorking));
return;
}
// Set the cursor
this.Cursor = Cursors.WaitCursor;
this.ScriptConsole.Cursor = Cursors.WaitCursor;
foreach (Form child in this.MdiChildren)
child.Cursor = Cursors.WaitCursor;
// Force a whole form refresh (to draw over residue menus, etc.)
this.Refresh();
}
///
/// A thread-safe method for setting the progress indicator.
/// The indicator is reset once 100 has been reached.
///
/// This method is thread-safe.
///
public void SetApplicationProgress(int progress)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
this.Invoke(new IApplicationSetProgressCallback(this.SetApplicationProgress), progress);
return;
}
// Set progress bar value
progress = (progress > this.progressStatus.Maximum) ? this.progressStatus.Maximum : progress;
this.progressStatus.Value = progress;
// Reset the progressbar (if required)
if (progress >= 100)
{
this.progressStatus.Value = 0;
}
else if (progress != 0)
{
// Set the label
this.lblStatus.Text = ((string)this.lblStatus.Tag) + progress.ToString("00") + "%";
this.lblStatus.Invalidate();
this.statusStrip.Refresh();
}
}
///
/// A thread-safe method for setting the status message.
///
/// This method is thread-safe.
///
public void SetApplicationStatusLabel(string status)
{
// Ensure the application is still valid
if (this == null || this.IsDisposed)
return;
// Make the call thread-safe
if (this.InvokeRequired)
{
if (!this.IsDisposed)
this.Invoke(new IApplicationSetStatusLabelCallback(this.SetApplicationStatusLabel), status);
return;
}
// Set the label
this.lblStatus.Text = status;
this.lblStatus.Tag = status;
this.lblStatus.Invalidate();
this.statusStrip.Refresh();
}
///
/// A thread-safe method setting the application as ready.
/// This method sets the cursor to the default and resets
/// the status label after the given pause.
///
/// This method is thread-safe.
/// The time (in milliseconds) to wait before resetting the status label.
/// If pause less than or equal to 0, the label is reset immediately.
public void SetApplicationAsReady(int pause)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
this.Invoke(new IApplicationSetAsReadyCallback(this.SetApplicationAsReady), pause);
return;
}
// Set the cursor
this.Cursor = Cursors.Default;
this.ScriptConsole.Cursor = Cursors.Default;
foreach (Form child in this.MdiChildren)
child.Cursor = Cursors.Default;
if (pause > 0)
{
// Set the status label to READY after the given pause,
// only set once (ie. period = Infinite)
ParameterizedThreadStart start = new ParameterizedThreadStart(this.SetApplicationAsReadyAfterPause);
Thread thread = new Thread(start);
thread.Name = "SetApplicationAsReadyAfterPause";
thread.Start(pause);
}
else
{
// Set status label immediately
this.SetApplicationStatusLabel(STATUS_READY);
}
}
///
/// Sets the status label to "Ready..." after the given pause.
///
///
public void SetApplicationAsReadyAfterPause(object oPause)
{
Thread.Sleep((int)oPause);
if (!this.IsDisposed)
if (this.lblStatus.Text.Contains("Completed"))
this.SetApplicationStatusLabel(STATUS_READY);
}
///
/// A thread-safe method for showing a Renderer in the
/// Application. The Renderer is added as an MDI child,
/// and the application watches various Renderer events
/// to keep Metadata.
///
/// This method is thread-safe.
///
public void ShowRenderer(siRenderer renderer)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
this.Invoke(new IApplicationRendererCallback(this.ShowRenderer), renderer);
return;
}
// Check renderer is not null
if (renderer == null)
return;
// Add the renderer to the Application Metadata
if (!this.Renderers.Contains(renderer))
this.Renderers.Add(renderer);
// Setup various Application controlled events, etc.
renderer.MouseDown += new MouseEventHandler(Renderer_MouseDown);
renderer.MouseMove += new MouseEventHandler(Renderer_MouseMove);
renderer.Closed += new siRenderer.siRendererHandler(Renderer_Closed);
// Show the renderer
renderer.Show(this);
renderer.Focus();
this.ScriptConsole.Focus();
}
///
/// Shows the given image in a new siGdiSliceRenderer.
///
///
/// This method is thread-safe.
///
///
public siRenderer ShowImageInNewRenderer(itk.itkImageBase image)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
object result = this.Invoke(new IApplicationImageCallback(this.ShowImageInNewRenderer), image);
return result as siRenderer;
}
// Check the image is not null
if (image == null) return null;
// Show the image in a new renderer
siGdiSliceRenderer newRenderer = new siGdiSliceRenderer( this );
newRenderer.Inputs.Add(image);
newRenderer.Initialise();
this.ShowRenderer(newRenderer);
return newRenderer;
}
///
/// A thread-safe method for adding a Tool Form to the Application
/// as a tab page.
///
/// This method is thread-safe.
///
public void AddTool(siFormTool form)
{
// Make the call thread-safe
if (this.InvokeRequired)
{
this.Invoke(new IApplicationAddToolCallback(this.AddTool), form);
return;
}
// Check form is not null
if (form == null)
return;
// Configure form
form.FormClosed += new FormClosedEventHandler(FormTool_FormClosed);
Crownwood.Magic.Controls.TabPage page = new Crownwood.Magic.Controls.TabPage(form.Text, form, form.Icon);
page.ContextMenu = this.ScriptConsole.ContextMenu;
page.Tag = form;
this.ShowTabRight();
this.tabRight.TabPages.Add(page);
this.tabRight.SelectedTab = page;
}
private void FormTool_FormClosed(object sender, FormClosedEventArgs e)
{
this.tabRight.TabPages.Remove(this.tabRight.TabPages[(sender as Form).Text]);
}
//=====================================================================
#endregion
//=====================================================================
#endregion
#region Open Methods
//=====================================================================
siRecentFileManager m_RecentOpenImage;
private void MenuFileOpen_Click(object sender, EventArgs e)
{
// Open an image and display it. Discard the image object.
this.OpenImage(true, null);
}
private void MenuFileOpenSeries_Click(object sender, EventArgs e)
{
siFormOpenSeries osd = new siFormOpenSeries();
DialogResult result = osd.ShowDialog(this);
if (result == DialogResult.OK)
this.OpenImageSeries(osd.PixelType, 3, osd.Files.ToArray());
}
private void MenuFileOpenSOMetafile_Click(object sender, EventArgs e)
{
try
{
// Setup the dialog
siOpenSpatialObjectDialog osod = new siOpenSpatialObjectDialog();
osod.Filter = "Meta Header files (*.mhd)|*.mhd";
osod.FilterIndex = 1;
osod.DefaultExt = "mhd";
osod.Title = "Open SpatialObject Metafile...";
DialogResult result = osod.ShowDialog(this);
if (result == DialogResult.OK)
{
// Assume it is a scene
itk.itkSpatialObjectReader_F3 reader = itk.itkSpatialObjectReader_F3.New();
reader.FileName = osod.FileName;
reader.Update();
siDataObjectDecorator scene = new siDataObjectDecorator(reader.Scene);
scene.Metadata["RenderingMethod"] = siSpatialObjectRenderingMethod.Wireframe;
scene.Metadata["RenderingSlices"] = 50;
scene.Metadata["TubeRenderingMethod"] = siTubeSpatialObjectRenderingMethod.PolyCone;
scene.Size = osod.Size;
scene.Spacing = osod.Spacing;
scene.Origin = osod.Origin;
// Create renderer
siVolumeRenderer renderer = new siVolumeRenderer(this);
renderer.Inputs.Add(scene);
renderer.Initialise();
// Create editor
siFormRendererEditor editor = new siFormRendererEditor(renderer);
// Show everything
this.AddTool(editor);
this.ShowRenderer(renderer);
renderer.Repaint();
}
else if (result == DialogResult.Abort)
{
// Show user message
string caption = "Unable to open SpatialObject metafile";
string text = "The size and/or spacing for the SpatialObject was incorrectly specified.";
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
catch (Exception ex)
{
// Show user message
string caption = "Unable to open SpatialObject metafile";
string text = "Unable to open SpatialObject metafile.\r\n\r\n" + ex.ToString();
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
// Set application as ready
this.SetApplicationAsReady(0);
}
}
///
/// Show the open image dialog with the given title.
/// The image is read and returned on success.
///
/// True and the image is displayed in a default renderer, otherwise the image is not displayed.
/// The title of the dialog. If the title is null or empty, the default title is used.
/// The opened image or null on cancel/failure.
public itk.itkImageBase OpenImage(bool display, string title)
{
// Make the call thread-safe
if (this.InvokeRequired)
return (itk.itkImage)this.Invoke(new IApplicationOpenImageCallback2(this.OpenImage), new object[] { display, title } );
// Setup the image dialog
siOpenImageDialog oid = new siOpenImageDialog();
oid.Filter = "Meta Header files (*.mhd,*.mha)|*.mhd;*.mha";
oid.Filter += "|PNG Image files (*.png)|*.png";
oid.Filter += "|JPEG Image files (*.jpg)|*.jpg";
oid.Filter += "|BMP Image files (*.bmp)|*.bmp";
oid.Filter += "|TIFF Image files (*.tif)|*.tif";
oid.Filter += "|VTK Image files (*.vtk)|*.vtk";
oid.Filter += "|All Image files (*.mhd,*.mha,*.png,*.jpg,*.bmp,*.tif,*.vtk)|*.mhd;*.mha;*.png;*.jpg;*.bmp;*.tif;*.vtk";
oid.Filter += "|All files (*.*)|*.*";
oid.FilterIndex = 7;
oid.DefaultExt = "mhd";
oid.PixelType = itk.itkPixelTypeEnum.UnsignedChar;
oid.Dimensions = 2;
// Set the dialog title
if (title != null && title.Length > 0)
oid.Title = title;
// Show the dialog
if (oid.ShowDialog(this) == DialogResult.OK)
{
try
{
// TODO: At the moment, oid.NumberOfComponentsPerPixel returns 0 for variable length vectors
itk.itkPixelType pixelType = new itk.itkPixelType(oid.PixelType, oid.PixelArray, oid.NumberOfComponentsPerPixel);
return this.OpenImage(display, pixelType, (int)oid.Dimensions, oid.FileName);
}
catch (Exception ex)
{
// Show user message
string caption = "Unable to open image file";
string text = "Unable to open image file.\r\n\r\n" + ex.ToString();
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
// Set application as ready
this.SetApplicationAsReady(0);
}
}
// User selected cancel, return null
return null;
}
///
/// Show the open image dialog with the given title, pixeltype and dimension.
/// The image is read and returned on success.
///
/// True and the image is displayed in a default renderer, otherwise the image is not displayed.
/// The title of the dialog. If the title is null or empty, the default title is used.
/// The type of the image to open.
///
public itk.itkImageBase OpenImage(bool display, string title, itk.itkImageBase image)
{
if (image == null)
return null;
else
return this.OpenImage(display, title, image.PixelType, (int)image.Dimension);
}
///
/// Show the open image dialog with the given title, pixeltype and dimension.
/// The image is read and returned on success.
///
/// True and the image is displayed in a default renderer, otherwise the image is not displayed.
/// The title of the dialog. If the title is null or empty, the default title is used.
/// The pixel type of the image to open. The pixel type combobox is NOT displayed.
/// The dimension of the image to open. The dimension combobox is NOT displayed.
///
public itk.itkImageBase OpenImage(bool display, string title, itk.itkPixelType pixelType, int dim)
{
// Make the call thread-safe
if (this.InvokeRequired)
return (itk.itkImageBase)this.Invoke(new IApplicationOpenImageCallback4(this.OpenImage), new object[] { display, title, pixelType, dim });
// Setup the image dialog
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Meta Header files (*.mhd,*.mha)|*.mhd;*.mha";
ofd.Filter += "|PNG Image files (*.png)|*.png";
ofd.Filter += "|JPEG Image files (*.jpg)|*.jpg";
ofd.Filter += "|BMP Image files (*.bmp)|*.bmp";
ofd.Filter += "|TIFF Image files (*.tif)|*.tif";
ofd.Filter += "|VTK Image files (*.vtk)|*.vtk";
ofd.Filter += "|All Image files (*.mhd,*.mha,*.png,*.jpg,*.bmp,*.tif,*.vtk)|*.mhd;*.mha;*.png;*.jpg;*.bmp;*.tif;*.vtk";
ofd.FilterIndex = 7;
ofd.DefaultExt = "mhd";
// Set the dialog title
if (title != null && title.Length > 0)
ofd.Title = title;
else
ofd.Title = "Open image";
// Show the dialog
if (ofd.ShowDialog(this) == DialogResult.OK)
{
return this.OpenImage(display, pixelType, dim, ofd.FileName);
}
// User selected cancel, return null
return null;
}
private itk.itkImageBase OpenImage(bool display, itk.itkPixelType pixelType, int dim, string fullPath)
{
// Create the image type
itk.itkImageBase image = itk.itkImage.New(pixelType, (uint)dim);
// Propagate call
return this.OpenImage(display, image, fullPath);
}
///
/// Open an image in a new renderer from a given path and type string.
/// For example: "C:/Temp/test1.png#F2"
///
/// The path and type of the image to open.
///
public itk.itkImageBase OpenImage(String pathAndTypeString)
{
// Separate the path and type
int index = pathAndTypeString.LastIndexOf("#");
if (index > -1)
{
String path = pathAndTypeString.Substring(0, index);
String imageType = pathAndTypeString.Substring(index + 1);
itk.itkImage image = itk.itkImage.New(imageType);
return this.OpenImage(true, image, path);
}
else
{
throw new ArgumentException("The image path, name, and/or type is invalid. Expecting path/name.ext#type, but received " + pathAndTypeString);
}
}
private itk.itkImageBase OpenImage(bool display, itk.itkImageBase image, String fullPath)
{
// Setup UI for reading
this.SetApplicationStatusLabel("Reading " + Path.GetFileName(fullPath) + "...");
this.SetApplicationAsWorking();
// Start thread
ParameterizedThreadStart start = new ParameterizedThreadStart(this.ReadImageWorker);
Thread thread = new Thread(start);
thread.Name = "ReadImage";
ImageParams p = new ImageParams(image, fullPath);
thread.Start(p);
// Refresh application, and wait for thread the finish
this.Refresh();
thread.Join();
thread = null;
// Check result
if (!p.Success)
{
// Show error message
string caption = "Unable to open image file";
string text = "Unable to open image file.\r\n\r\n" + p.Exception.ToString();
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else if (image != null && !image.IsDisposed)
{
// Check we should display the image
if (display)
{
// Create renderer
siGdiSliceRenderer renderer = new siGdiSliceRenderer(this);
renderer.Inputs.Add(image);
renderer.Initialise();
this.ShowRenderer(renderer);
// Add to recent files
// NOTE: Only add to recent files if we displayed the image
this.m_RecentOpenImage.AddFile(p.FullPath + "#" + image.MangledTypeString);
this.RefreshRecentOpenImageMenu();
}
}
// Reset UI
this.SetApplicationAsReady(0);
// Return the image
return image;
}
void ReadImageWorker(Object oParams)
{
// Cast to image
ImageParams p = oParams as ImageParams;
try
{
// Read image
p.Image.Read(p.FullPath);
p.Success = true;
}
catch (Exception ex)
{
p.Exception = ex;
p.Success = false;
}
}
private void OpenImageSeries(itk.itkPixelType pixelType, int dim, string[] files)
{
// Setup UI for reading
this.SetApplicationStatusLabel("Opening image series...");
this.SetApplicationAsWorking();
// Create the image
itk.itkImageBase image = itk.itkImage.New(pixelType, (uint)dim);
// Start thread
ParameterizedThreadStart start = new ParameterizedThreadStart(this.ReadImageSeriesWorker);
Thread thread = new Thread(start);
thread.Name = "ReadImageSeries";
ImageSeriesParams p = new ImageSeriesParams(image, files);
thread.Start(p);
// Refresh application, and wait for thread the finish
this.Refresh();
thread.Join();
thread = null;
// Check result
if (!p.Success)
{
// Show error message
string caption = "Unable to open image series";
string text = "Unable to open image series.\r\n\r\n" + p.Exception.ToString();
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else if (image != null && !image.IsDisposed)
{
// Create renderer
siGdiSliceRenderer renderer = new siGdiSliceRenderer(this);
renderer.Inputs.Add(image);
renderer.Initialise();
this.ShowRenderer(renderer);
}
// Reset UI
this.SetApplicationAsReady(0);
}
void ReadImageSeriesWorker(Object oParams)
{
// Cast to image
ImageSeriesParams p = oParams as ImageSeriesParams;
try
{
// Read image
p.Image.ReadSeries(p.Files);
p.Success = true;
}
catch (Exception ex)
{
p.Exception = ex;
p.Success = false;
}
}
private void RefreshRecentOpenImageMenu()
{
this.menuFileRecent.DropDownItems.Clear();
int index = 1;
for (int i = 0; i < this.m_RecentOpenImage.Count; i++)
{
siRecentFileManager.siRecentFileEntry entry = this.m_RecentOpenImage[i];
if (entry.FileExists)
{
ToolStripMenuItem menuFileRecentOpenItem = new ToolStripMenuItem(entry.GetFormattedInfoString(index));
menuFileRecentOpenItem.Tag = entry;
menuFileRecentOpenItem.Click += new EventHandler(MenuFileRecentItem_Click);
this.menuFileRecent.DropDownItems.Add(menuFileRecentOpenItem);
index++;
}
}
this.menuFileRecent.Enabled = (this.menuFileRecent.DropDownItems.Count > 0);
}
private void MenuFileRecentItem_Click(object sender, EventArgs e)
{
// Get the recent file info (ie. full path and mangled type string)
siRecentFileManager.siRecentFileEntry entry = (siRecentFileManager.siRecentFileEntry)(sender as ToolStripMenuItem).Tag;
string caption = "Could not open recent file";
string text = "Could not open recent file: '" + entry.FullInfo + "'.";
try
{
if (entry.FilePath != null && entry.FilePath.Length > 0 &&
File.Exists(entry.FilePath))
{
// Open the image and display it
itk.itkImageBase image = itk.itkImage.New(entry.TypeString.TrimStart('I'));
this.OpenImage(true, image, entry.FilePath);
return;
}
else
{
throw new FileNotFoundException("Image file does not exist.", entry.FilePath);
}
}
catch (Exception ex)
{
// Remove from list
this.m_RecentOpenImage.RemoveFile(entry.FullInfo);
this.RefreshRecentOpenImageMenu();
// Show warning to user
Trace.WriteLine(ex.ToString());
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
this.SetApplicationAsReady(0);
}
}
//=====================================================================
#endregion
#region Close/Exit Methods
//=====================================================================
private void ExitApplication()
{
//Persist the recent files
this.m_RecentOpenImage.PersistToRegistry();
this.m_RecentOpenImage = null;
this.m_RecentExecuteScripts.PersistToRegistry();
this.m_RecentExecuteScripts = null;
// Close all renderers
siRenderer[] renderers = this.Renderers.ToArray();
foreach (siRenderer renderer in renderers)
renderer.Close();
this.Renderers.Clear();
this.m_Renderers = null;
// Clear the Metadata
this.m_Metadata.Clear();
this.m_Metadata = null;
// Clear the script console
this.m_ScriptConsole.Clear();
this.m_ScriptConsole.Dispose();
this.m_ScriptConsole = null;
// Force an exit
try { Application.ExitThread(); }
catch (Exception ex) { Trace.WriteLine(ex); }
}
private void MenuFileClose_Click(object sender, EventArgs e)
{
if (this.CurrentRenderer != null)
this.CurrentRenderer.Close();
}
private void MenuFileCloseAll_Click(object sender, EventArgs e)
{
//Get a copy of all the renderers
siRenderer[] renders = this.Renderers.ToArray();
// Close all renderers
foreach (siRenderer renderer in renders)
renderer.Close();
// Clear the Metadata
this.Renderers.Clear();
}
private void MenuFileExit_Click(object sender, EventArgs e)
{
// Close the main form
this.Close();
}
//=====================================================================
#endregion
#region Save Methods
//=====================================================================
private void MenuFileSave_Click(object sender, EventArgs e)
{
this.SaveImage();
}
private void MenuFileSaveAs_Click(object sender, EventArgs e)
{
this.SaveImageAs();
}
///
/// Saves the first input of the current renderer.
///
public void SaveImage()
{
// Ensure we have a Renderer with a valid image
if (this.CurrentRenderer == null ||
this.CurrentRenderer.Inputs.Count == 0 ||
!(this.CurrentRenderer.Inputs[0] is itk.itkImageBase))
return;
// Check the name a valid file path
string fullPath = this.CurrentRenderer.Inputs[0].Name;
if (File.Exists(fullPath))
this.SaveImageAs(this.CurrentRenderer.Inputs[0] as itk.itkImageBase, fullPath, false);
else
this.SaveImageAs();
}
///
/// Saves the first input of the current renderer to the given path.
///
///
public void SaveImageAs(string fullPath)
{
// Ensure we have a Renderer with a valid image
if (this.CurrentRenderer == null ||
this.CurrentRenderer.Inputs.Count == 0 ||
!(this.CurrentRenderer.Inputs[0] is itk.itkImageBase))
return;
// Save the image
this.SaveImageAs(this.CurrentRenderer.Inputs[0] as itk.itkImageBase, fullPath, false);
}
private void SaveImageAs()
{
try
{
// Ensure we have a Renderer with a valid image
if (this.CurrentRenderer == null ||
this.CurrentRenderer.Inputs.Count == 0 ||
!(this.CurrentRenderer.Inputs[0] is itk.itkImageBase))
return;
// Get the image
itk.itkImageBase image = this.CurrentRenderer.Inputs[0] as itk.itkImageBase;
// Create dialog
siSaveImageDialog sid = new siSaveImageDialog();
sid.Filter = "Meta Header files (*.mhd,*.mha)|*.mhd;*.mha";
sid.Filter += "|PNG Image files (*.png)|*.png";
sid.Filter += "|JPEG Image files (*.jpg)|*.jpg";
sid.Filter += "|BMP Image files (*.bmp)|*.bmp";
sid.Filter += "|TIFF Image files (*.tif)|*.tif";
sid.Filter += "|VTK Image files (*.vtk)|*.vtk";
sid.Filter += "|All Image files (*.mhd,*.mha,*.png,*.jpg,*.bmp,*.tif,*.vtk)|*.mhd;*.mha;*.png;*.jpg;*.bmp;*.tif;*.vtk";
sid.FilterIndex = 7;
sid.DefaultExt = "mhd";
sid.PixelType = image.PixelType.TypeAsEnum;
sid.PixelArray = image.PixelType.ArrayAsEnum;
sid.ShowDimensions = false;
sid.ShowPixelArray = image.PixelType.IsArray;
// Try to extract filename
string ext = Path.GetExtension(image.Name);
string[] exts = ext.Split(' ');
string filename = Path.GetFileNameWithoutExtension(image.Name);
if (exts.Length == 1)
filename += exts[0];
else if (exts.Length >= 2)
filename += "_" + exts[1].Trim('(', ')', '_') + exts[0];
sid.FileName = filename;
// Show dialog
if (sid.ShowDialog(this) == DialogResult.OK)
{
// Check if the actual and selected pixel types are the same
if (sid.PixelType != image.PixelType.TypeAsEnum ||
sid.PixelArray != image.PixelType.ArrayAsEnum)
{
// Not the same: cast to the given type
itk.itkImageBase imageWithUserPixelType = itk.itkImage.New(new itk.itkPixelType(sid.PixelType, sid.PixelArray, image.PixelType.NumberOfComponentsPerPixel), image.Dimension);
itk.itkImageToImageFilter filterCast;
if (sid.PixelArray == itk.itkPixelArrayEnum.Scalar)
filterCast = itk.itkCastImageFilter.New(image, imageWithUserPixelType);
else
filterCast = itk.itkVectorCastImageFilter.New(image, imageWithUserPixelType);
filterCast.RemoveAllObservers();
filterCast.SetInput(image);
filterCast.Update();
filterCast.GetOutput(imageWithUserPixelType);
imageWithUserPixelType.DisconnectPipeline();
(filterCast as IDisposable).Dispose();
filterCast = null;
image = imageWithUserPixelType;
}
// Save
this.SaveImageAs(image, sid.FileName, sid.UseCompression);
}
}
catch (Exception ex)
{
// Show user message
string caption = "Unable to save image file";
string text = "Unable to save image file.\r\n\r\n" + ex.ToString();
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
// Set application as ready
this.SetApplicationAsReady(0);
}
}
private void SaveImageAs(itk.itkImageBase image, string fullPath, bool compress)
{
// Setup UI for reading
this.SetApplicationStatusLabel("Writing " + Path.GetFileName(fullPath) + "...");
this.SetApplicationAsWorking();
// Start thread
ParameterizedThreadStart start = new ParameterizedThreadStart(this.WriteImageWorker);
Thread thread = new Thread(start);
thread.Name = "WriteImage";
ImageParams p = new ImageParams(image, fullPath, compress);
thread.Start(p);
// Refresh application, and wait for thread the finish
this.Refresh();
thread.Join();
thread = null;
// Check result
if (!p.Success)
{
// Show error message
string caption = "Unable to save image file";
string text = "Unable to save file.\r\n\r\n" + p.Exception.ToString();
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
// Add to recent files
this.m_RecentOpenImage.AddFile(p.FullPath + "#" + (image as itk.INativePointer).MangledTypeString);
this.RefreshRecentOpenImageMenu();
// Set the image name
image.Name = fullPath;
this.Refresh();
}
// Reset UI - this does not have to be thread safe
this.SetApplicationAsReady(0);
}
void WriteImageWorker(object oParams)
{
// Cast to image
ImageParams p = (ImageParams)oParams;
try
{
// Write image
itk.itkImageFileWriter writer = itk.itkImageFileWriter.New(p.Image);
writer.SetInput(p.Image);
writer.FileName = p.FullPath;
writer.UseCompression = p.Compress;
writer.Update();
p.Success = true;
}
catch (Exception ex)
{
p.Success = false;
p.Exception = ex;
}
}
//=====================================================================
#endregion
#region Help Methods
//=====================================================================
private void MenuHelpAbout_Click(object sender, EventArgs e)
{
siFormAbout about = new siFormAbout();
about.ShowDialog(this);
}
//=====================================================================
#endregion
#region Renderer Methods
//=====================================================================
void Renderer_Closed(siRenderer renderer, EventArgs e)
{
// Remove from list
this.Renderers.Remove(renderer);
// Dispose
renderer.Dispose();
renderer = null;
}
void Renderer_MouseMove(object sender, MouseEventArgs e)
{
// Cast sender to renderer
siRenderer renderer = null;
if (sender != null && sender is siRenderer)
renderer = sender as siRenderer;
else
return;
// Check that renderer has the needed Metadata variables
if (!renderer.Metadata.ContainsKey("IsMouseInsideImageSpace") ||
!renderer.Metadata.ContainsKey("LastImagePointMouseMove") ||
!renderer.Metadata.ContainsKey("LastImageIndexMouseMove") ||
!renderer.Metadata.ContainsKey("LastImagePixelMouseMove"))
return;
// Check the mouse is inside the image
bool isMouseInsideImageSpace = (bool)renderer.Metadata["IsMouseInsideImageSpace"];
if (!isMouseInsideImageSpace)
this.lblImageLocation.Text = "None";
else
{
// Show the point, index, and value
itk.itkPoint point = (itk.itkPoint)renderer.Metadata["LastImagePointMouseMove"];
itk.itkIndex index = (itk.itkIndex)renderer.Metadata["LastImageIndexMouseMove"];
itk.itkPixel pixel = (itk.itkPixel)renderer.Metadata["LastImagePixelMouseMove"];
// Pass the point through the direction transform
itk.itkImageBase input = renderer.Inputs[0] as itk.itkImageBase;
point = renderer.DirectionTransformPoint(point);
// Show the location information
if (point != null && index != null && pixel != null)
this.lblImageLocation.Text = index.ToString("000") + " " + point.ToString() + " " + pixel.ToString();
else
this.lblImageLocation.Text = "None";
}
}
void Renderer_MouseDown(object sender, MouseEventArgs e)
{
if (sender != null && sender is siRenderer)
(sender as siRenderer).Focus();
}
//=====================================================================
#endregion
#region IronPython Scripting Methods
//=====================================================================
siRecentFileManager m_RecentExecuteScripts;
private void MenuScriptExecute_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.CheckFileExists = true;
ofd.CheckPathExists = true;
ofd.Filter = "IronPython Script files (*.py)|*.py";
ofd.FilterIndex = 0;
ofd.Multiselect = false;
ofd.RestoreDirectory = true;
ofd.ShowHelp = false;
ofd.Title = "Please browse the script to execute...";
DialogResult result = ofd.ShowDialog(this);
if (result == DialogResult.OK)
this.ExecuteScript(ofd.FileName);
}
private void MenuScriptAbort_Click(object sender, EventArgs e)
{
// TODO: Abort the script
}
private void ExecuteScript(string fullPathScript)
{
// Only execute a script if there is a valid renderer selected
if (this.CurrentRenderer == null ||
this.CurrentRenderer.Inputs.Count == 0)
return;
// Refresh the Application
this.Refresh();
this.SetApplicationAsWorking();
// Add to recent files
this.m_RecentExecuteScripts.AddFile(fullPathScript);
this.RefreshRecentExecuteScriptsMenu();
// Create a ScriptManager to execute the script
siScriptManager manager = new siScriptManager(this, fullPathScript);
manager.ScriptFinalised += new siScriptManager.ScriptHandler(Manager_ScriptScriptFinalised);
manager.ExecuteScript();
}
void ScriptConsole_UserEnteredScriptCommand(string command)
{
// Refresh the Application
this.Refresh();
this.SetApplicationAsWorking();
// Get the current directory
// TODO: Allow the user to change the current directory
string cd = Application.StartupPath;
// Create a manager from the command and execute
siScriptManager manager = siScriptManager.CreateFromCommand(this, command, cd);
if (manager != null)
{
manager.ScriptFinalised += new siScriptManager.ScriptHandler(Manager_ScriptScriptFinalised);
manager.ExecuteScript();
}
else
{
// Tell the console to re-enter immediate mode
this.ScriptConsole.EnterImmediateMode();
}
}
private void Manager_ScriptScriptFinalised(siScriptManager manager)
{
// Dispose of the manager
manager.Dispose();
manager = null;
// Tell the console to re-enter immediate mode
this.ScriptConsole.EnterImmediateMode();
}
private void RefreshRecentExecuteScriptsMenu()
{
this.menuScriptRecent.DropDownItems.Clear();
for (int i = 1; i < this.m_RecentExecuteScripts.Count; i++)
{
siRecentFileManager.siRecentFileEntry entry = this.m_RecentExecuteScripts[i];
ToolStripMenuItem menuScriptRecentItem = new ToolStripMenuItem(entry.GetFormattedInfoString(i));
menuScriptRecentItem.Tag = entry;
menuScriptRecentItem.Image = Resources.Script;
menuScriptRecentItem.Click += new EventHandler(MenuScriptRecentItem_Click);
this.menuScriptRecent.DropDownItems.Add(menuScriptRecentItem);
}
this.menuScriptRecent.Enabled = (this.menuScriptRecent.DropDownItems.Count > 0);
}
private void MenuScriptRecentItem_Click(object sender, EventArgs e)
{
// Get the recent script full path
siRecentFileManager.siRecentFileEntry entry = (siRecentFileManager.siRecentFileEntry)(sender as ToolStripMenuItem).Tag;
if (File.Exists(entry.FilePath))
this.ExecuteScript(entry.FilePath);
else
{
// Show warning to user
string caption = "Could not execute recent script";
string text = "Could not execute recent script: '" + entry.FilePath + "'.";
this.ShowMessageBox(text, caption, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
// Remove from list
this.m_RecentExecuteScripts.RemoveFile(entry.FullInfo);
this.RefreshRecentExecuteScriptsMenu();
}
}
private void MenuScriptConsole_Click(object sender, EventArgs e)
{
if (this.tabBottom.TabPages["Script Console"] == null)
{
// Add console to tabs
Crownwood.Magic.Controls.TabPage page = new Crownwood.Magic.Controls.TabPage("Script Console", ScriptConsole, ScriptConsole.Icon);
page.ContextMenu = this.ScriptConsole.ContextMenu;
this.tabBottom.TabPages.Add(page);
}
// Toggle bottom tab
if (this.tabBottom.Visible)
{
this.HideTabBottom();
}
else
{
this.ShowTabBottom();
this.ScriptConsole.Focus();
}
}
//=====================================================================
#endregion
#region DEBUG: Test Methods
//=====================================================================
#if DEBUG
private void menuTextureRendering_Click(object sender, EventArgs e)
{
try
{
// Open a test image
itk.itkImage_UC3 imageValue = itk.itkImage_UC3.New();
imageValue.Read(@"C:\DanMueller\Data\VolVis\engine.mhd");
imageValue.Metadata["Value"] = true;
itk.itkImage_UC3 imageGradMag = itk.itkImage_UC3.New();
imageGradMag.Read(@"C:\DanMueller\Data\VolVis\engine_GradientMagnitude.mhd");
imageGradMag.Metadata["GradientMagnitude"] = true;
// Create transfer function
itk.itkSize size = new itk.itkSize(256, 256);
string[] layers = { "Layer1", "Layer2" };
siTransferFunction tf = new siTransferFunction(size, layers);
siFormTransferFunctionEditor editorTf = new siFormTransferFunctionEditor(tf);
// Create renderer
siVolumeRenderer renderer = new siVolumeRenderer(this);
renderer.Closed += new siRenderer.siRendererHandler(editorTf.OnRendererClosed);
renderer.Metadata["VertexProgram"] = @"C:\Utils\SharpImage\Source\Rendering\VolumeRendering\shader-vm.vert";
renderer.Metadata["FragmentProgram"] = @"C:\Utils\SharpImage\Source\Rendering\VolumeRendering\shader-vm.frag";
renderer.Metadata["TransferFunction"] = tf;
renderer.Inputs.Add(imageValue);
renderer.Inputs.Add(imageGradMag);
renderer.Initialise();
// Create renderer editor
siFormRendererEditor editorRenderer = new siFormRendererEditor(renderer);
// Show everything
this.AddTool(editorTf);
this.AddTool(editorRenderer);
this.ShowRenderer(renderer);
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
}
private int m_Iteration = 0;
void filter_Iteration(itk.itkObject sender)
{
this.SetApplicationProgress(m_Iteration++);
}
void filter_Progress(itk.itkProcessObject sender, float progress)
{
this.SetApplicationProgress((int)(progress * 100.0F));
}
void filter_Ended(itk.itkObject sender, DateTime time)
{
this.ScriptConsole.WriteLine((sender as itk.itkProcessObject).Name + " Finished: " + time.ToString());
}
void filter_Started(itk.itkObject sender, DateTime time)
{
this.ScriptConsole.WriteLine((sender as itk.itkProcessObject).Name + " Started: " + time.ToString());
}
private void menuTransferFunction_Click(object sender, EventArgs e)
{
// Open background
itk.itkImage_UC2 back = itk.itkImage_UC2.New();
back.Read("C:/Temp/C_ValueEdgeHistogram.png");
itk.itkSize size = new itk.itkSize(512, 128);
string[] arrayLayers = { "Context", "Heart", "Arteries" };
List layers = new List(arrayLayers);
siTransferFunction tf = new siTransferFunction(size, layers);
tf.BackgroundImage = back;
tf.Modified += new siTransferFunction.siTransferFunctionModifiedHandler(tf_Modified);
siFormTransferFunctionEditor editor = new siFormTransferFunctionEditor(tf);
(this as IApplication).AddTool(editor);
}
void tf_Modified(siTransferFunction sender, bool partial)
{
//sender.PaintToImage();
//sender.Image.Write("C:/temp/Test1.mhd");
}
private void menuTubeRendering_Click(object sender, EventArgs e)
{
//// Open a test image
//itk.itkImage_UC3 imageValue = itk.itkImage_UC3.New();
//imageValue.Read(@"C:\temp\engine.mhd");
//imageValue.Metadata["Value"] = true;
//itk.itkImage_UC3 imageGradMag = itk.itkImage_UC3.New();
//imageGradMag.Read(@"C:\temp\engine_GradientMagnitude.mhd");
//imageGradMag.Metadata["GradientMagnitude"] = true;
//// Create transfer function
//itk.itkSize size = new itk.itkSize(256, 256);
//string[] layers = { "Layer1", "Layer2" };
//siTransferFunction tf = new siTransferFunction(size, layers);
//siFormTransferFunctionEditor editorTf = new siFormTransferFunctionEditor(tf);
//// Open spatial object scene
//siSceneSpatialObject scene = siSceneSpatialObject.New();
//scene.Metadata["TubeRenderingMethod"] = siTubeSpatialObjectRenderingMethod.PolyCone;
//scene.Metadata["TubeRenderingStyle"] = siTubeSpatialObjectRenderingStyle.Surface;
//scene.Metadata["RenderingSlices"] = 50;
//scene.Read("C:/Temp/Test2.mhd");
//scene.Size = imageValue.Size;
//scene.Spacing = imageValue.Spacing;
//scene.Origin = imageValue.Origin;
//// Create renderer
//siVolumeRenderer renderer = new siVolumeRenderer(this);
//renderer.Inputs.Add(imageValue);
//renderer.Inputs.Add(imageGradMag);
//renderer.Inputs.Add(scene);
//renderer.Metadata["TransferFunction"] = tf;
//renderer.Metadata["VertexProgram"] = @"C:\Dan\SVN_WORK\Software\ITK\SharpImage\trunk\Source\Rendering\VolumeRendering\shader-vm.vert";
//renderer.Metadata["FragmentProgram"] = @"C:\Dan\SVN_WORK\Software\ITK\SharpImage\trunk\Source\Rendering\VolumeRendering\shader-vm.frag";
//renderer.Initialise();
//renderer.Closed += editorTf.OnRendererClosed;
//// Create renderer editor
//siFormRendererEditor editorRenderer = new siFormRendererEditor(renderer);
//// Show everything
//this.AddTool(editorTf);
//this.AddTool(editorRenderer);
//this.ShowRenderer(renderer);
}
#endif
//=====================================================================
#endregion
}
}