Creating Render Windows

<< Click to Display Table of Contents >>

Navigation:  XStream® HDVR® SDK > Implementation Concepts > Rendering Concepts > Rendering Images >

Creating Render Windows

Previous pageReturn to chapter overviewNext page

C++ C++ Java Java .NET .NET

Summary

 

The XStream® HDVR® SDK allows creation of an unlimited number of windows or views into the same dataset. An application can have multiple simultaneous views with different render settings and camera perspectives, contained in a RENDER_PARAMS structure. Multiple datasets can be viewed simultaneously as well. Once an image has been rendered it is displayed on screen. The process of rendering a window to screen is platform specific, and depends on the operating system and the XStream HDVR SDK language currently in use. This section discusses how to display a rendered image under various development languages and platforms. These examples assume that images are being rendered using the IRenderQueue (hdrcRenderQueue) class.

 

Refer to the RenderEngineContext vs RenderQueue section for detailed information regarding the use of the IRenderQueue and hdrcRenderQueue classes discussed on this page.

 

Microsoft MFC (C++)

 

Applications written using the Microsoft MFC framework use the XStream HDVR C++ API. These applications make use of the MFC framework to render images in user interface objects derived from the MFC CWnd class.

 

The IRenderQueue object first sets an IRQFrameListener object that will receive frame data from the server.

 

pRenderQueue->SetFrameListener(pFrameListener);

 

The rendering server will deliver frames to the IRQFrameListener::RawFrameReady() method. If compression has been selected, this method should return H_TRUE in the pRet output parameter to request that the client decompress the image and pass the converted frame to the IRQFrameListener::ConvertedFrameReady() method. If no compression has been selected, the IRQFrameListener::RawFrameReady() method can handle the frame data, or it can return H_TRUE to pass control directly to the IRQFrameListener::ConvertedFrameReady() method. This method should record the width, height, and frame data for the new image and then send a WM_PAINT message to cause the window to redraw the image.

 

RRESULT CFrameListener::RawFrameReady(h_boolean *pRet, const VOLVISIMAGE *imm, const RENDER_PARAMS *rp, const h_boolean bFinal) {

   *pRet = H_TRUE;

   return S_OK;

}

 

RRESULT CFrameListener::ConvertedFrameReady(const VOLVISIMAGE *pImage, const RENDER_PARAMS *rp) {

   if(pImage->Data != NULL) {

      width = pImage->Width;

      height = pImage->Height;

      imgData = (unsigned char*)pImage->Data;

      valid = true;

      ::SendMessage(m_hWnd,WM_PAINT,0,0);

   }

   return S_OK;

}

 

Sending a WM_PAINT message causes the MFC framework to call the application's OnPaint() handler method. This is the method in which the XStream HDVR image data is displayed on screen.

 

void CClientAppDlg::OnPaint() {

   if(IsIconic()) {

      CDialog::OnPaint();

   } else {

      CDialog::OnPaint();

      if(m_pFrameGrabber && m_pFrameGrabber->valid == true) {

         CWnd *staticDlg = GetDlgItem(IDC_STATIC);

 

         BITMAPINFO bmi;

         ZeroMemory(&bmi, sizeof(bmi));

 

         bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

         bmi.bmiHeader.biWidth = m_pFrameGrabber->width;

         bmi.bmiHeader.biHeight = -m_pFrameGrabber->height;

         bmi.bmiHeader.biPlanes = 1;

         bmi.bmiHeader.biBitCount = 24;

         bmi.bmiHeader.biCompression = BI_RGB;

 

         RECT rect;

         GetDlgItem(IDC_STATIC)->GetClientRect(&rect);

 

         StretchDIBits(staticDlg->GetDC()->m_hDC, 

            0, 0, rect.right-rect.left, rect.bottom - rect.top,

            0, 0, rect.right-rect.left, rect.right  - rect.left, 

            m_pFrameGrabber->imgData, &bmi, DIB_RGB_COLORS, SRCCOPY);

      }

   }

}

 

Microsoft .NET (C# / .NET)

 

Applications written using the Microsoft .NET framework use the XStream HDVR .NET API and are generally written using the Microsoft C# language. These applications make use of the Windows Forms framework render images in user interface objects derived from the .NET Form class.

 

The hdrcRenderQueue object first sets a hdrcRQFrameListener object that will receive frame data from the server.

 

renderQueue.setFrameListener(frameListener);

 

The rendering server will deliver frames to the hdrcRQFrameListener::rawFrameReady() method. These frames may be compressed (if compression was selected) or uncompressed. Both compressed and uncompressed images should be handled directly by the hdrcRQFrameListener::rawFrameReady() method. This method should be used to decompress the image if necessary, and initialize a Windows Forms System.Drawing.Bitmat object with the frame data. This Bitmap object should then be passed to a System.Windows.Forms.Form object for rendering.

 

public bool rawFrameReady(VOLVISIMAGE volvisimage, RENDER_PARAMS renderparams, bool b) {

   if (volvisimage.Data == null) {

      return false;

   }

 

   // let's determine what .NET image we should create

   PixelFormat format;

   int imgSize = volvisimage.Width*volvisimage.Height;

   if (volvisimage.Type == hdrcDefines.__Fields.IMAGE_TYPE_RGB) {

      imgSize *= 3;

      format = PixelFormat.Format24bppRgb;

   }

   else {

      format = PixelFormat.Format8bppIndexed;

   }

 

   // if it's compressed, let's decompress it

   if (volvisimage.CompressionType == hdrcDefines.__Fields.COMPRESSION_TYPE_JPEG) {

      byte [] dest = new byte[imgSize];

 

      // this calls a native library call for fast JPEG decompression. Both .NET and Java

      // fail to provide adequate JPEG decompression speed in their standard libraries.

      com.fovia.hdrcext.JNICalls.decompressJPEG8(dest, dest.Length, volvisimage.Data, volvisimage.Data.Length);

 

      volvisimage.CompressionType = hdrcDefines.__Fields.COMPRESSION_TYPE_NONE;

      volvisimage.Data = dest;

   }

 

   // if we haven't created the image or the size has changed we should allocate.

   if (m_bitmap == null || m_bitmap.PixelFormat != format || 

      m_bitmap.Width != volvisimage.Width || m_bitmap.Height != volvisimage.Height) 

   {

      m_bitmap = new Bitmap(volvisimage.Width, volvisimage.Height, format);

 

      // apply a simple greyscale palette if we getting an indexed image (thin rendering modes)

      if (format == PixelFormat.Format8bppIndexed) {

         ColorPalette pal = GetColorPalette();

         for (int i = 0; i < 256; i++) {

            pal.Entries[i] = System.Drawing.Color.FromArgb(i, i, i);

         }

 

         m_bitmap.Palette = pal;

      }

   }

 

   // copy the raw image data into the Image.

   BitmapData data = m_bitmap.LockBits(new Rectangle(0, 0, m_bitmap.Width, m_bitmap.Height), ImageLockMode.WriteOnly, format);

 

   if ((format == PixelFormat.Format24bppRgb && data.Stride != m_bitmap.Width * 3) ||

   (format == PixelFormat.Format8bppIndexed && data.Stride != m_bitmap.Width))

   {

      MessageBox.Show("There's padding in this image!");

      return false;

   }

 

   Marshal.Copy(volvisimage.Data, 0, data.Scan0, volvisimage.Data.Length);

   m_bitmap.UnlockBits(data);

 

   // set the image and request a repaint

   m_form.setImage(m_bitmap);

   m_form.Invalidate();

 

   // Return false to indicate that we don't want to pass the image data to the hdrcRQFrameListener::rawFrameReady() method.

   return false;

}

 

Within a Windows System.Windows.Forms.Form object, the Bitmap object is rendered using the Form's Paint event handler.

 

// Access function used in code example above.

public void setImage(Image img) {

   // Save out the image for the paint call

   m_image = img;

}

 

private void Form1_Paint(object sender, PaintEventArgs e) {

   Graphics g = e.Graphics;

 

  if (m_image != null) {

     g.DrawImageUnscaled(m_image, 0, 0);

  }

}

 

Java

 

Applications written using the the XStream HDVR Java API can optionally make use of the Java Swing user interface classes to render images to JPanel derived objects. XStream HDVR Java API provides classes to simplify use of the Java Swing API.