using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Rx.NET;
using Rx.ApiLF.NET;
namespace RxExApiCluCS
{
public partial class FormMain : Form
{
// The CLUViz Control instance
CLUViz.NET.ViewCtrl m_xCluView;
// The CLUViz Engine instance
CLUViz.NET.EngineCtrl m_xCluEngine;
// A slider for changing the focus
RxNET.GUI.RxSliderHoriz m_xSliderFocus;
// This variable holds the handle to the currently loaded ray image
uint m_uRay = 0;
///
/// Constructor
///
public FormMain()
{
InitializeComponent();
// Initialize the slider
m_xSliderFocus = new RxNET.GUI.RxSliderHoriz();
m_xSliderFocus.Title = "Focus";
// Set this to zero, so that software reacts directly to user input.
m_xSliderFocus.ValueChangedEventDelay = 0;
// Set the starting slider value (0.5) and its range [0.0,1.0].
m_xSliderFocus.SetValueRange(0.5, 0.0, 1.0);
// Add an event handler to the ValueChanged event, so that we can react to it
m_xSliderFocus.ValueChanged += new EventHandler(m_xSliderFocus_ValueChanged);
// Throw the slider control into a flow control panel
panelCtrl.Controls.Add(m_xSliderFocus);
}
///
/// Initialize visualization for new image
///
private void NewImage()
{
Rx.NET.ImageFormat xImgF = new Rx.NET.ImageFormat();
// Read image format of resultant refocused image.
// The RxApi holds a number of result images on the CUDA card,
// so that they are only copied back to the host memory when needed.
RxApiLF.RxGetImageFormat(EImgID.Focus, ref xImgF);
// Initialize the CLUScript variables iWidth and iHeight with
// the dimensions of the refocused image.
m_xCluView.SetVarNumber("iWidth", xImgF.iWidth);
m_xCluView.SetVarNumber("iHeight", xImgF.iHeight);
// Execute the script with ToolName == "Image_Create".
// This prepared the image view for an image of the given size.
// The image itself is not copied at this point.
m_xCluView.ExecScript("Image_Create");
string[] asText = new string[1];
bool bError = false;
m_xCluView.GetScriptOutput(ref asText, ref bError);
// If the refocused image is of luminance type, we need to select
// a different shader for the image display.
if (xImgF.ePixelType == Rx.InteropNet.Runtime28.EPixelType.Lum
|| xImgF.ePixelType == Rx.InteropNet.Runtime28.EPixelType.LumA)
{
m_xCluView.ExecScript("Image_Lum_Enable");
m_xCluView.GetScriptOutput(ref asText, ref bError);
}
int iTexID = 0;
// Get the OpenGL texture ID of the texture that will contain the
// displayed image.
m_xCluView.GetVarNumber("texImage", ref iTexID);
// Register this texture ID with the RxApi, as the texture ID
// for displaying the refocused image. The texture is automatically
// (re-)initialized by this call to the correct type and size.
RxApiLF.RxSetPar(EPar.Gl_TexFocusLeftID, (uint)iTexID);
// Copy the refocused image held on the CUDA device to the OpenGL texture
// with ID iTexID.
RxApiLF.RxGlUpdateTex((uint)EImgID.Focus);
// Tell the CLU control to redraw the current scene tree.
// This does not re-execute the script itself.
// It needs to be called to ensure that the new content of
// the image texture is displayed.
m_xCluView.Update();
}
///
/// Redisplay the image
///
private void UpdateImage()
{
// Update the OpenGL texture from CUDA memory.
RxApiLF.RxGlUpdateTex((uint)EImgID.Focus);
// Update the CLU control view
m_xCluView.Update();
}
///
/// Update the focus setting
///
private void UpdateFocus()
{
// Execute the actual refocusing on the currently bound ray image.
RxApiLF.RxFocusOnPlane(m_xSliderFocus.Value);
// Redisplay the refocused image
UpdateImage();
}
///
/// Event handler for focus slider.
///
///
///
private void m_xSliderFocus_ValueChanged(object sender, EventArgs e)
{
// Refocus from raw image
UpdateFocus();
}
///
/// React to user selecting "Load Ray Image..." from main menu
///
///
///
private void loadRayImageToolStripMenuItem_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "Ray Image|*.ray";
DialogResult diagRes = openFileDialog1.ShowDialog();
if (diagRes == DialogResult.OK)
{
uint uRay = 0;
// Load the ray image
if (!RxApiLF.RxRayLoad(ref uRay, openFileDialog1.FileName))
{
string sErr = "";
RxApiLF.RxGetLastError(ref sErr);
System.Windows.Forms.MessageBox.Show(sErr);
}
else
{
// Bind the loaded ray image, i.e. copy it to the CUDA device
RxApiLF.RxRayBind(uRay);
// If a previously loaded ray image exists, then it is not
// automatically deleted from memory when a new ray image
// is loaded. So we need to delete it explicitly.
if (m_uRay != 0)
RxApiLF.RxRayDelete(m_uRay);
// Remember handle to current ray image
m_uRay = uRay;
// Initialize image view, since new image may have different dimensions.
NewImage();
// And finally refocus the image.
UpdateFocus();
}
}
}
unsafe private void loadRawDataToolStripMenuItem_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "Raw Image File|*.png";
DialogResult diagRes = openFileDialog1.ShowDialog();
if (diagRes == DialogResult.OK)
{
Rx.NET.Image imgLF = new Rx.NET.Image();
Rx.NET.Image imgWhite = new Rx.NET.Image();
string sFilename = openFileDialog1.FileName;
FileInfo xInfo = new FileInfo(sFilename);
m_xCluView.SetVarString("sFilename", sFilename);
m_xCluView.ExecScript("Image_Read");
m_xCluView.GetVarImage("imgA", imgLF);
// Create a new ray image of the format that is to be used later.
// The ray image created here is just a black image with
// some dummy lightfield calibration values.
RxApiLF.RxRayNew(ref m_uRay, imgLF.Format);
// Bind that ray image.
RxApiLF.RxRayBind(m_uRay);
// Create the filename for the calibration XML data
string[] asPart = xInfo.Name.Split(new string[] {"."}, StringSplitOptions.RemoveEmptyEntries);
string sExt = asPart[1];
string sName = asPart[0];
sFilename = xInfo.DirectoryName + "\\" + sName + ".xml";
// Load the calibration data from an XML file
// Since the ray image is bound, this calibration data is
// also copied onto the CUDA device.
RxApiLF.RxRayCalibLoad(m_uRay, sFilename);
// alternatively, if the calibration data had been read before as XML string
// with RxApiLF.RxRayCalibXmlGet(m_uRay, sXml), the calibration can be set
// with RxApiLF.RxRayCalibXmlSet(m_uRay, sXml).
// Create the filename for the raw white image
asPart = sName.Split(new string[] { "_" }, StringSplitOptions.None);
asPart[asPart.Length - 1] = "RawWhite";
sName = String.Join("_", asPart);
sFilename = xInfo.DirectoryName + "\\" + sName + "." + sExt;
m_xCluView.SetVarString("sFilename", sFilename);
m_xCluView.ExecScript("Image_Read");
m_xCluView.GetVarImage("imgA", imgWhite);
// Create an image moniker to pass the image to RxApiLF
Rx.NET.ImageMoniker imgA = new Rx.NET.ImageMoniker();
imgA.Create(imgLF.Format);
// Set the image data pointer of the read image
// to the image moniker
imgA.SetDataPtr(imgLF.GetDataPtr());
// Now set the LF image
RxApiLF.RxSetImage(EImgID.Ray, imgA);
imgA.SetDataPtr(imgWhite.GetDataPtr());
// Now set the White image
RxApiLF.RxSetImage(EImgID.RayWhite, imgA);
// Set flag to normalize ray image with white image
RxApiLF.RxSetPar(EPar.Ray_ApplyWhiteImage, (UInt32)1);
// If the loaded image is a color image need also switch on Demosaicing
if (imgLF.Format.IsBayerPixelType())
{
RxApiLF.RxSetPar(EPar.Ray_ConvBayer, (UInt32)1);
}
// Now pre-process the loaded ray image
RxApiLF.RxPreProcess();
// Initialize image view, since new image may have different dimensions.
NewImage();
// And finally refocus the image.
UpdateFocus();
}
}
///
/// Event handler called, when Form is shown for the first time.
///
///
///
private void FormMain_Shown(object sender, EventArgs e)
{
// Initialize the RxApi. This always has to be called first.
RxApiLF.RxInit();
// Automatically select an appropriate CUDA device, that can
// directly communicate with an OpenGL rendering context.
// This allows us to directly copy images from CUDA memory to
// OpenGL texture memory, which is much faster, than first copying
// the image back to the host memory and then again to the
// OpenGl card.
// However, if CUDA/OpenGL interoperability is selected, we
// must create a local OpenGL rendering context and make it
// active in the same thread as the RxApi.
RxApiLF.RxCudaSelectDevice(-1, true);
// Start the CLU engine
m_xCluEngine = new CLUViz.NET.EngineCtrl();
m_xCluEngine.Start();
// Now create the CLU control and embed it into the "panelClu" control.
// Changes in size and position of panelClu are automatically applied
// to the CLU control.
// Since the CLU control display runs in a separate thread, we must
// create an OpenGL rendering context for the CUDA thread (this thread)
// that shares its texture memory with the OpenGL rendering context in
// the CLU control thread. This is done automatically by setting the second
// parameter to "true".
m_xCluView = new CLUViz.NET.ViewCtrl(panelClu, true, 0);
// We now have to make this shared rendering context current,
// since otherwise all CUDA commands will fail. That is,
// CUDA is only initialized once this rendering context is made current.
// Note that the shared rendering context for this thread is attached to
// an invisible dummy window that is held internally.
m_xCluView.MakeCurrentSharedRC();
// Now set the visualization CLUScript from the resources.
m_xCluView.SetScript(RxExApiCluCS.Properties.Resources.View_Image_01);
}
///
/// Uninitialize and free everything when the main form is closed
///
///
///
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
// End the CLU engine. This closes all CLU controls
m_xCluEngine.End();
// Finalize the RxApi. This frees all internal memory also on the CUDA device.
RxApiLF.RxFinalize();
}
}
}