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(); } } }