[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