[vtkusers] Java servlet + Glassfish + volume rendering applications problem

Emptystack wulihouxiaoshuai at 163.com
Wed Jan 21 00:43:26 EST 2015


My Java servlet code is as following:

package com.hou.service;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.hou.core.RenderContext;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import vtk.vtkActor;
import vtk.vtkConeSource;
import vtk.vtkJPEGWriter;
import vtk.vtkNativeLibrary;
import vtk.vtkPolyDataMapper;
import vtk.vtkRenderWindow;
import vtk.vtkRenderWindowInteractor;
import vtk.vtkRenderer;
import vtk.vtkUnsignedCharArray;
import vtk.vtkWindowToImageFilter;

public class Image extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

//	private RenderContext renderContext;

	// Load VTK library and print which library was not properly loaded
	static {
		if (!vtkNativeLibrary.LoadAllNativeLibraries()) {
			for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {
				if (!lib.IsLoaded()) {
					System.out.println(lib.GetLibraryName() + " not loaded");
				} else {
					System.out.println(lib.GetLibraryName() + " loaded");
				}
			}
		} else {
			System.out.println("All Libraries are loaded");
		}
		vtkNativeLibrary.DisableOutputWindow(null);
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		// super.doGet(req, resp);
		
		HttpSession session = req.getSession(false);
		
		int count;

        vtkConeSource cone;
        vtkPolyDataMapper mapper;
        vtkActor actor;
        vtkRenderer renderer;
        vtkRenderWindow renderWindow;
        vtkRenderWindowInteractor interactor;
        
		String countKey = "count";
		
        String coneKey	= "cone";
        String mapperKey = "mapper";
        String actorKey	= "actor";
        String rendererKey = "renderer";
        String renderWindowKey = "renderWindow";
        String interactorKey = "interactor";
        
		if (session == null) {
			session = req.getSession(true);
			
			count = 0;
			session.setAttribute(countKey, count);
						
			cone = new vtkConeSource();
			cone.SetHeight(3.0);
			cone.SetRadius(1.0);
			cone.SetResolution(10);
			session.setAttribute(coneKey, cone);
			
			mapper = new vtkPolyDataMapper();
			mapper.SetInputConnection(cone.GetOutputPort());
			session.setAttribute(mapperKey, mapper);
			
			actor = new vtkActor();
			actor.SetMapper(mapper);
			session.setAttribute(actorKey, actor);
			
			renderer = new vtkRenderer();
			renderer.AddActor(actor);
			session.setAttribute(rendererKey, renderer);
			
			renderWindow = new vtkRenderWindow();
			renderWindow.SetSize(300, 300);
			renderWindow.SetOffScreenRendering(1);
			renderWindow.AddRenderer(renderer);
			session.setAttribute(renderWindowKey, renderWindow);
			
			interactor = new vtkRenderWindowInteractor();
			interactor.SetRenderWindow(renderWindow);
			session.setAttribute(interactorKey, interactor);
			
			interactor.Initialize();
			interactor.Render();
		} else {
			interactor =
(vtkRenderWindowInteractor)session.getAttribute(interactorKey);
			renderWindow = (vtkRenderWindow)session.getAttribute(renderWindowKey);
			
			count = (int)session.getAttribute(countKey);
			count++;
			if (count == 1) {
				interactor.SetEventPosition(100, 100);
				interactor.SetLastEventPosition(100, 100);
				interactor.LeftButtonPressEvent();
			}
			else {
				interactor.LeftButtonPressEvent();
				interactor.SetEventPosition(110, 110);
				interactor.SetLastEventPosition(100, 100);
				interactor.MouseMoveEvent();
			}			
			session.setAttribute(countKey, count);
		}
		
		int[] size = renderWindow.GetSize();
	    		
		vtkUnsignedCharArray pixelDataArray = new vtkUnsignedCharArray();
		
		renderWindow.GetPixelData(0, 0, size[0] - 1, size[1] - 1,
				1-renderWindow.GetDoubleBuffer(), pixelDataArray);

		// convert unsigned char to byte,note the range of each primitive type
		byte[] bytePixelData = pixelDataArray.GetJavaArray();

		int[] RGBPixelData = new int[bytePixelData.length];

		// convert byte to unsigned and stored in RGBPixelData array
		for (int i = 0; i < RGBPixelData.length; i++) {
			RGBPixelData[i] = bytePixelData[i] & 0xff;
		}
		int[] pixelData = new int[size[0] * size[1]];

		int index = 0;
		int r, g, b;

		// The sequence of pixels is from left to right and from bottom to top,
		// so we need flip the RGB pixel
		// no A channel to avoid image distortion
		for (int row = size[1] - 1; row >= 0; row--) {
			for (int column = 0; column < size[0]; column++) {
				r = RGBPixelData[3 * (size[1] * row + column)];
				g = RGBPixelData[3 * (size[1] * row + column) + 1];
				b = RGBPixelData[3 * (size[1] * row + column) + 2];
				
				if (r > 255) {
					r = 255;
				}
				if (r < 0) {
					r = 0;
				}
				if (g > 255) {
					g = 255;
				}
				if (g < 0) {
					g = 0;
				}
				if (b > 255) {
					b = 255;
				}
				if (b < 0) {
					b = 0;
				}

				pixelData[index] = ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b &
0xff));
				index++;
			}

		}
		BufferedImage bi = new BufferedImage(size[0], size[1],
				BufferedImage.TYPE_INT_RGB);
		bi.getRaster().setDataElements(0, 0, size[0], size[1], pixelData);

		// get a ServletOutputStream for writing binary data
		ServletOutputStream so = resp.getOutputStream();
		// This creates an instance of a JPEGImageEncoder
		// that can be used to encode image data as JPEG Data streams.
		JPEGImageEncoder jie = JPEGCodec.createJPEGEncoder(so);
		// Encode a BufferedImage as a JPEG data stream
		jie.encode(bi);
		
		so.flush(); 
	}
}

I used a simple cone to test the rotation. And after several requests the
cone can be rotated. So I replaced the code with the following volume
rendering code :

package com.hou.service;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.hou.auxiliary.VolumeMapperType;
import com.hou.convertor.DicomImageImport;
import com.hou.core.RenderContext;
import com.hou.prop.ViewProp;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import vtk.vtkActor;
import vtk.vtkColorTransferFunction;
import vtk.vtkConeSource;
import vtk.vtkDICOMImageReader;
import vtk.vtkGPUVolumeRayCastMapper;
import vtk.vtkImageData;
import vtk.vtkImageShiftScale;
import vtk.vtkJPEGWriter;
import vtk.vtkNativeLibrary;
import vtk.vtkPiecewiseFunction;
import vtk.vtkPlaneSource;
import vtk.vtkPolyDataMapper;
import vtk.vtkRenderWindow;
import vtk.vtkRenderWindowInteractor;
import vtk.vtkRenderer;
import vtk.vtkSmartVolumeMapper;
import vtk.vtkUnsignedCharArray;
import vtk.vtkVolume;
import vtk.vtkVolumeMapper;
import vtk.vtkVolumeProperty;
import vtk.vtkVolumeRayCastMIPFunction;
import vtk.vtkVolumeRayCastMapper;
import vtk.vtkWindowToImageFilter;

public class Image extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

//	private RenderContext renderContext;

	// Load VTK library and print which library was not properly loaded
	static {
		if (!vtkNativeLibrary.LoadAllNativeLibraries()) {
			for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {
				if (!lib.IsLoaded()) {
					System.out.println(lib.GetLibraryName() + " not loaded");
				} else {
					System.out.println(lib.GetLibraryName() + " loaded");
				}
			}
		} else {
			System.out.println("All Libraries are loaded");
		}
		vtkNativeLibrary.DisableOutputWindow(null);
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		// super.doGet(req, resp);
		
		HttpSession session = req.getSession(false);
		
		int count;
		
		vtkDICOMImageReader reader;
        vtkGPUVolumeRayCastMapper mapper;
        vtkColorTransferFunction colorTransferFunction;
        vtkPiecewiseFunction opacityFunction;
        vtkVolumeProperty volumeProperty;
        vtkVolume volume;
        vtkRenderer renderer;
        vtkRenderWindow renderWindow;
        vtkRenderWindowInteractor interactor;
        
		String countKey = "count";
		
        String readerKey = "reader";
        String colorTFKey = "colorTF";
        String opacityTFKey = "opacityTF";
        String mapperKey = "mapper";
        String volumePropertyKey = "volumeProperty";
        String volumeKey	= "volume";
        String rendererKey = "renderer";
        String renderWindowKey = "renderWindow";
        String interactorKey = "interactor";
        
		if (session == null) {
			session = req.getSession(true);
			
			reader = new vtkDICOMImageReader();
			reader.SetDirectoryName("/home/garnett/image/CT");
			reader.Update();
			session.setAttribute(readerKey, reader);
			
			
			colorTransferFunction = new vtkColorTransferFunction();
			colorTransferFunction.AddRGBPoint(-3024, 0.0, 0.0, 0.0);
			colorTransferFunction.AddRGBPoint(42.9, 0.55, 0.25, 0.15);
			colorTransferFunction.AddRGBPoint(184.4, 0.92, 0.64, 0.06);
			colorTransferFunction.AddRGBPoint(277.64, 1.0, 0.88, 0.62);
			colorTransferFunction.AddRGBPoint(1430, 1.0, 0.99, 0.95);		
			session.setAttribute(colorTFKey, colorTransferFunction);
			
			opacityFunction = new vtkPiecewiseFunction();
			opacityFunction.AddPoint(-3024, 0.0);
			opacityFunction.AddPoint(42.9, 0.0);
			opacityFunction.AddPoint(163.5, 0.429);
			opacityFunction.AddPoint(277.64, 0.777);
			opacityFunction.AddPoint(1430, 0.758);
			session.setAttribute(opacityTFKey, opacityFunction);
			
			volumeProperty = new vtkVolumeProperty();
			volumeProperty.SetColor(colorTransferFunction);
			volumeProperty.SetScalarOpacity(opacityFunction);
			volumeProperty.SetInterpolationTypeToLinear();
			volumeProperty.ShadeOn();
			volumeProperty.SetAmbient(0.1);
			volumeProperty.SetDiffuse(0.9);
			volumeProperty.SetSpecular(0.2);
			volumeProperty.SetSpecularPower(10.0);
			volumeProperty.SetScalarOpacityUnitDistance(0.8919);
			session.setAttribute(volumePropertyKey, volumeProperty);
			
			mapper = new vtkGPUVolumeRayCastMapper();
			mapper.SetBlendModeToComposite();
			mapper.SetInput(reader.GetOutput());
			mapper.Update();
			session.setAttribute(mapperKey, mapper);
											        
			volume = new vtkVolume();
			volume.SetMapper(mapper);
			volume.SetProperty(volumeProperty);
			session.setAttribute(volumeKey, volume);

			count = 0;
			session.setAttribute(countKey, count);
									
			renderer = new vtkRenderer();
			renderer.AddVolume(volume);
			session.setAttribute(rendererKey, renderer);
			
			renderWindow = new vtkRenderWindow();
			renderWindow.SetSize(300, 300);
			renderWindow.SetOffScreenRendering(1);
			renderWindow.AddRenderer(renderer);
			session.setAttribute(renderWindowKey, renderWindow);
			
			interactor = new vtkRenderWindowInteractor();
			interactor.SetRenderWindow(renderWindow);
			session.setAttribute(interactorKey, interactor);
			
			interactor.Initialize();
			interactor.Render();
		} else {
			interactor =
(vtkRenderWindowInteractor)session.getAttribute(interactorKey);
			renderWindow = (vtkRenderWindow)session.getAttribute(renderWindowKey);
			
			count = (int)session.getAttribute(countKey);
			count++;
			if (count == 1) {
				interactor.SetEventPosition(100, 100);
				interactor.SetLastEventPosition(100, 100);
				interactor.LeftButtonPressEvent();
				interactor.LeftButtonReleaseEvent();
			}
			else {
				interactor.LeftButtonPressEvent();
				interactor.SetEventPosition(110, 110);
				interactor.SetLastEventPosition(100, 100);
				interactor.MouseMoveEvent();
				interactor.LeftButtonReleaseEvent();
			}			
			session.setAttribute(countKey, count);
		}
		
		int[] size = renderWindow.GetSize();
	    		
		vtkUnsignedCharArray pixelDataArray = new vtkUnsignedCharArray();
		
		renderWindow.GetPixelData(0, 0, size[0] - 1, size[1] - 1,
				1-renderWindow.GetDoubleBuffer(), pixelDataArray);

		// convert unsigned char to byte,note the range of each primitive type
		byte[] bytePixelData = pixelDataArray.GetJavaArray();

		int[] RGBPixelData = new int[bytePixelData.length];

		// convert byte to unsigned and stored in RGBPixelData array
		for (int i = 0; i < RGBPixelData.length; i++) {
			RGBPixelData[i] = bytePixelData[i] & 0xff;
		}
		int[] pixelData = new int[size[0] * size[1]];

		int index = 0;
		int r, g, b;

		// The sequence of pixels is from left to right and from bottom to top,
		// so we need flip the RGB pixel
		// no A channel to avoid image distortion
		for (int row = size[1] - 1; row >= 0; row--) {
			for (int column = 0; column < size[0]; column++) {
				r = RGBPixelData[3 * (size[1] * row + column)];
				g = RGBPixelData[3 * (size[1] * row + column) + 1];
				b = RGBPixelData[3 * (size[1] * row + column) + 2];
				
				if (r > 255) {
					r = 255;
				}
				if (r < 0) {
					r = 0;
				}
				if (g > 255) {
					g = 255;
				}
				if (g < 0) {
					g = 0;
				}
				if (b > 255) {
					b = 255;
				}
				if (b < 0) {
					b = 0;
				}

				pixelData[index] = ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b &
0xff));
				index++;
			}

		}
		BufferedImage bi = new BufferedImage(size[0], size[1],
				BufferedImage.TYPE_INT_RGB);
		bi.getRaster().setDataElements(0, 0, size[0], size[1], pixelData);

		// get a ServletOutputStream for writing binary data
		ServletOutputStream so = resp.getOutputStream();
		// This creates an instance of a JPEGImageEncoder
		// that can be used to encode image data as JPEG Data streams.
		JPEGImageEncoder jie = JPEGCodec.createJPEGEncoder(so);
		// Encode a BufferedImage as a JPEG data stream
		jie.encode(bi);
		
		so.flush(); 
	}


}

The first request still can get the image, but the second request failed.
After some debugging works, I hav found that the problem happeneded at the
interactor.MouseMoveEvent() method which invokes the
vtkRenderWindowInteractor::Render() method. I don't know why it crashed at
this place.  Is there something wrong with my java servlet code? I have been
confused with this problem for several months. 
Looking forward to your reply!
Best fishes! 
 



--
View this message in context: http://vtk.1045678.n5.nabble.com/Java-servlet-Glassfish-volume-rendering-applications-problem-tp5730017p5730190.html
Sent from the VTK - Users mailing list archive at Nabble.com.


More information about the vtkusers mailing list