<div dir="ltr">You might run into a concurrency issue.<div>VTK is not thread safe, and the way Glassfish is handling servlet may result in concurrency.</div><div>You did not notice it before because the rendering was faster in surface mode. But for volume rendering, the server side might already be in a Render() call when a new one occurs.</div><div><br></div><div>On a side note, why don't you use VTK Web or ParaViewWeb?</div><div><br></div><div>Seb</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 20, 2015 at 10:43 PM, Emptystack <span dir="ltr"><<a href="mailto:wulihouxiaoshuai@163.com" target="_blank">wulihouxiaoshuai@163.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">My Java servlet code is as following:<br>
<br>
package com.hou.service;<br>
<br>
import java.awt.image.BufferedImage;<br>
import java.io.File;<br>
import java.io.FileInputStream;<br>
import java.io.FileNotFoundException;<br>
import java.io.FileOutputStream;<br>
import java.io.IOException;<br>
<br>
import javax.imageio.ImageIO;<br>
import javax.servlet.ServletException;<br>
import javax.servlet.ServletOutputStream;<br>
import javax.servlet.http.HttpServlet;<br>
import javax.servlet.http.HttpServletRequest;<br>
import javax.servlet.http.HttpServletResponse;<br>
import javax.servlet.http.HttpSession;<br>
<br>
import com.hou.core.RenderContext;<br>
import com.sun.image.codec.jpeg.JPEGCodec;<br>
import com.sun.image.codec.jpeg.JPEGImageEncoder;<br>
<br>
import vtk.vtkActor;<br>
import vtk.vtkConeSource;<br>
import vtk.vtkJPEGWriter;<br>
import vtk.vtkNativeLibrary;<br>
import vtk.vtkPolyDataMapper;<br>
import vtk.vtkRenderWindow;<br>
import vtk.vtkRenderWindowInteractor;<br>
import vtk.vtkRenderer;<br>
import vtk.vtkUnsignedCharArray;<br>
import vtk.vtkWindowToImageFilter;<br>
<br>
public class Image extends HttpServlet {<br>
<br>
        /**<br>
         *<br>
         */<br>
        private static final long serialVersionUID = 1L;<br>
<br>
//      private RenderContext renderContext;<br>
<br>
        // Load VTK library and print which library was not properly loaded<br>
        static {<br>
                if (!vtkNativeLibrary.LoadAllNativeLibraries()) {<br>
                        for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {<br>
                                if (!lib.IsLoaded()) {<br>
                                        System.out.println(lib.GetLibraryName() + " not loaded");<br>
                                } else {<br>
                                        System.out.println(lib.GetLibraryName() + " loaded");<br>
                                }<br>
                        }<br>
                } else {<br>
                        System.out.println("All Libraries are loaded");<br>
                }<br>
                vtkNativeLibrary.DisableOutputWindow(null);<br>
        }<br>
<br>
        @Override<br>
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)<br>
                        throws ServletException, IOException {<br>
                // TODO Auto-generated method stub<br>
                // super.doGet(req, resp);<br>
<br>
                HttpSession session = req.getSession(false);<br>
<br>
                int count;<br>
<br>
        vtkConeSource cone;<br>
        vtkPolyDataMapper mapper;<br>
        vtkActor actor;<br>
        vtkRenderer renderer;<br>
        vtkRenderWindow renderWindow;<br>
        vtkRenderWindowInteractor interactor;<br>
<br>
                String countKey = "count";<br>
<br>
        String coneKey  = "cone";<br>
        String mapperKey = "mapper";<br>
        String actorKey = "actor";<br>
        String rendererKey = "renderer";<br>
        String renderWindowKey = "renderWindow";<br>
        String interactorKey = "interactor";<br>
<br>
                if (session == null) {<br>
                        session = req.getSession(true);<br>
<br>
                        count = 0;<br>
                        session.setAttribute(countKey, count);<br>
<br>
                        cone = new vtkConeSource();<br>
                        cone.SetHeight(3.0);<br>
                        cone.SetRadius(1.0);<br>
                        cone.SetResolution(10);<br>
                        session.setAttribute(coneKey, cone);<br>
<br>
                        mapper = new vtkPolyDataMapper();<br>
                        mapper.SetInputConnection(cone.GetOutputPort());<br>
                        session.setAttribute(mapperKey, mapper);<br>
<br>
                        actor = new vtkActor();<br>
                        actor.SetMapper(mapper);<br>
                        session.setAttribute(actorKey, actor);<br>
<br>
                        renderer = new vtkRenderer();<br>
                        renderer.AddActor(actor);<br>
                        session.setAttribute(rendererKey, renderer);<br>
<br>
                        renderWindow = new vtkRenderWindow();<br>
                        renderWindow.SetSize(300, 300);<br>
                        renderWindow.SetOffScreenRendering(1);<br>
                        renderWindow.AddRenderer(renderer);<br>
                        session.setAttribute(renderWindowKey, renderWindow);<br>
<br>
                        interactor = new vtkRenderWindowInteractor();<br>
                        interactor.SetRenderWindow(renderWindow);<br>
                        session.setAttribute(interactorKey, interactor);<br>
<br>
                        interactor.Initialize();<br>
                        interactor.Render();<br>
                } else {<br>
                        interactor =<br>
(vtkRenderWindowInteractor)session.getAttribute(interactorKey);<br>
                        renderWindow = (vtkRenderWindow)session.getAttribute(renderWindowKey);<br>
<br>
                        count = (int)session.getAttribute(countKey);<br>
                        count++;<br>
                        if (count == 1) {<br>
                                interactor.SetEventPosition(100, 100);<br>
                                interactor.SetLastEventPosition(100, 100);<br>
                                interactor.LeftButtonPressEvent();<br>
                        }<br>
                        else {<br>
                                interactor.LeftButtonPressEvent();<br>
                                interactor.SetEventPosition(110, 110);<br>
                                interactor.SetLastEventPosition(100, 100);<br>
                                interactor.MouseMoveEvent();<br>
                        }<br>
                        session.setAttribute(countKey, count);<br>
                }<br>
<br>
                int[] size = renderWindow.GetSize();<br>
<br>
                vtkUnsignedCharArray pixelDataArray = new vtkUnsignedCharArray();<br>
<br>
                renderWindow.GetPixelData(0, 0, size[0] - 1, size[1] - 1,<br>
                                1-renderWindow.GetDoubleBuffer(), pixelDataArray);<br>
<br>
                // convert unsigned char to byte,note the range of each primitive type<br>
                byte[] bytePixelData = pixelDataArray.GetJavaArray();<br>
<br>
                int[] RGBPixelData = new int[bytePixelData.length];<br>
<br>
                // convert byte to unsigned and stored in RGBPixelData array<br>
                for (int i = 0; i < RGBPixelData.length; i++) {<br>
                        RGBPixelData[i] = bytePixelData[i] & 0xff;<br>
                }<br>
                int[] pixelData = new int[size[0] * size[1]];<br>
<br>
                int index = 0;<br>
                int r, g, b;<br>
<br>
                // The sequence of pixels is from left to right and from bottom to top,<br>
                // so we need flip the RGB pixel<br>
                // no A channel to avoid image distortion<br>
                for (int row = size[1] - 1; row >= 0; row--) {<br>
                        for (int column = 0; column < size[0]; column++) {<br>
                                r = RGBPixelData[3 * (size[1] * row + column)];<br>
                                g = RGBPixelData[3 * (size[1] * row + column) + 1];<br>
                                b = RGBPixelData[3 * (size[1] * row + column) + 2];<br>
<br>
                                if (r > 255) {<br>
                                        r = 255;<br>
                                }<br>
                                if (r < 0) {<br>
                                        r = 0;<br>
                                }<br>
                                if (g > 255) {<br>
                                        g = 255;<br>
                                }<br>
                                if (g < 0) {<br>
                                        g = 0;<br>
                                }<br>
                                if (b > 255) {<br>
                                        b = 255;<br>
                                }<br>
                                if (b < 0) {<br>
                                        b = 0;<br>
                                }<br>
<br>
                                pixelData[index] = ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b &<br>
0xff));<br>
                                index++;<br>
                        }<br>
<br>
                }<br>
                BufferedImage bi = new BufferedImage(size[0], size[1],<br>
                                BufferedImage.TYPE_INT_RGB);<br>
                bi.getRaster().setDataElements(0, 0, size[0], size[1], pixelData);<br>
<br>
                // get a ServletOutputStream for writing binary data<br>
                ServletOutputStream so = resp.getOutputStream();<br>
                // This creates an instance of a JPEGImageEncoder<br>
                // that can be used to encode image data as JPEG Data streams.<br>
                JPEGImageEncoder jie = JPEGCodec.createJPEGEncoder(so);<br>
                // Encode a BufferedImage as a JPEG data stream<br>
                jie.encode(bi);<br>
<br>
                so.flush();<br>
        }<br>
}<br>
<br>
I used a simple cone to test the rotation. And after several requests the<br>
cone can be rotated. So I replaced the code with the following volume<br>
rendering code :<br>
<br>
package com.hou.service;<br>
<br>
import java.awt.image.BufferedImage;<br>
import java.io.File;<br>
import java.io.FileInputStream;<br>
import java.io.FileNotFoundException;<br>
import java.io.FileOutputStream;<br>
import java.io.IOException;<br>
<br>
import javax.imageio.ImageIO;<br>
import javax.servlet.ServletException;<br>
import javax.servlet.ServletOutputStream;<br>
import javax.servlet.http.HttpServlet;<br>
import javax.servlet.http.HttpServletRequest;<br>
import javax.servlet.http.HttpServletResponse;<br>
import javax.servlet.http.HttpSession;<br>
<br>
import com.hou.auxiliary.VolumeMapperType;<br>
import com.hou.convertor.DicomImageImport;<br>
import com.hou.core.RenderContext;<br>
import com.hou.prop.ViewProp;<br>
import com.sun.image.codec.jpeg.JPEGCodec;<br>
import com.sun.image.codec.jpeg.JPEGImageEncoder;<br>
<br>
import vtk.vtkActor;<br>
import vtk.vtkColorTransferFunction;<br>
import vtk.vtkConeSource;<br>
import vtk.vtkDICOMImageReader;<br>
import vtk.vtkGPUVolumeRayCastMapper;<br>
import vtk.vtkImageData;<br>
import vtk.vtkImageShiftScale;<br>
import vtk.vtkJPEGWriter;<br>
import vtk.vtkNativeLibrary;<br>
import vtk.vtkPiecewiseFunction;<br>
import vtk.vtkPlaneSource;<br>
import vtk.vtkPolyDataMapper;<br>
import vtk.vtkRenderWindow;<br>
import vtk.vtkRenderWindowInteractor;<br>
import vtk.vtkRenderer;<br>
import vtk.vtkSmartVolumeMapper;<br>
import vtk.vtkUnsignedCharArray;<br>
import vtk.vtkVolume;<br>
import vtk.vtkVolumeMapper;<br>
import vtk.vtkVolumeProperty;<br>
import vtk.vtkVolumeRayCastMIPFunction;<br>
import vtk.vtkVolumeRayCastMapper;<br>
import vtk.vtkWindowToImageFilter;<br>
<br>
public class Image extends HttpServlet {<br>
<br>
        /**<br>
         *<br>
         */<br>
        private static final long serialVersionUID = 1L;<br>
<br>
//      private RenderContext renderContext;<br>
<br>
        // Load VTK library and print which library was not properly loaded<br>
        static {<br>
                if (!vtkNativeLibrary.LoadAllNativeLibraries()) {<br>
                        for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {<br>
                                if (!lib.IsLoaded()) {<br>
                                        System.out.println(lib.GetLibraryName() + " not loaded");<br>
                                } else {<br>
                                        System.out.println(lib.GetLibraryName() + " loaded");<br>
                                }<br>
                        }<br>
                } else {<br>
                        System.out.println("All Libraries are loaded");<br>
                }<br>
                vtkNativeLibrary.DisableOutputWindow(null);<br>
        }<br>
<br>
        @Override<br>
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)<br>
                        throws ServletException, IOException {<br>
                // TODO Auto-generated method stub<br>
                // super.doGet(req, resp);<br>
<br>
                HttpSession session = req.getSession(false);<br>
<br>
                int count;<br>
<br>
                vtkDICOMImageReader reader;<br>
        vtkGPUVolumeRayCastMapper mapper;<br>
        vtkColorTransferFunction colorTransferFunction;<br>
        vtkPiecewiseFunction opacityFunction;<br>
        vtkVolumeProperty volumeProperty;<br>
        vtkVolume volume;<br>
        vtkRenderer renderer;<br>
        vtkRenderWindow renderWindow;<br>
        vtkRenderWindowInteractor interactor;<br>
<br>
                String countKey = "count";<br>
<br>
        String readerKey = "reader";<br>
        String colorTFKey = "colorTF";<br>
        String opacityTFKey = "opacityTF";<br>
        String mapperKey = "mapper";<br>
        String volumePropertyKey = "volumeProperty";<br>
        String volumeKey        = "volume";<br>
        String rendererKey = "renderer";<br>
        String renderWindowKey = "renderWindow";<br>
        String interactorKey = "interactor";<br>
<br>
                if (session == null) {<br>
                        session = req.getSession(true);<br>
<br>
                        reader = new vtkDICOMImageReader();<br>
                        reader.SetDirectoryName("/home/garnett/image/CT");<br>
                        reader.Update();<br>
                        session.setAttribute(readerKey, reader);<br>
<br>
<br>
                        colorTransferFunction = new vtkColorTransferFunction();<br>
                        colorTransferFunction.AddRGBPoint(-3024, 0.0, 0.0, 0.0);<br>
                        colorTransferFunction.AddRGBPoint(42.9, 0.55, 0.25, 0.15);<br>
                        colorTransferFunction.AddRGBPoint(184.4, 0.92, 0.64, 0.06);<br>
                        colorTransferFunction.AddRGBPoint(277.64, 1.0, 0.88, 0.62);<br>
                        colorTransferFunction.AddRGBPoint(1430, 1.0, 0.99, 0.95);<br>
                        session.setAttribute(colorTFKey, colorTransferFunction);<br>
<br>
                        opacityFunction = new vtkPiecewiseFunction();<br>
                        opacityFunction.AddPoint(-3024, 0.0);<br>
                        opacityFunction.AddPoint(42.9, 0.0);<br>
                        opacityFunction.AddPoint(163.5, 0.429);<br>
                        opacityFunction.AddPoint(277.64, 0.777);<br>
                        opacityFunction.AddPoint(1430, 0.758);<br>
                        session.setAttribute(opacityTFKey, opacityFunction);<br>
<br>
                        volumeProperty = new vtkVolumeProperty();<br>
                        volumeProperty.SetColor(colorTransferFunction);<br>
                        volumeProperty.SetScalarOpacity(opacityFunction);<br>
                        volumeProperty.SetInterpolationTypeToLinear();<br>
                        volumeProperty.ShadeOn();<br>
                        volumeProperty.SetAmbient(0.1);<br>
                        volumeProperty.SetDiffuse(0.9);<br>
                        volumeProperty.SetSpecular(0.2);<br>
                        volumeProperty.SetSpecularPower(10.0);<br>
                        volumeProperty.SetScalarOpacityUnitDistance(0.8919);<br>
                        session.setAttribute(volumePropertyKey, volumeProperty);<br>
<br>
                        mapper = new vtkGPUVolumeRayCastMapper();<br>
                        mapper.SetBlendModeToComposite();<br>
                        mapper.SetInput(reader.GetOutput());<br>
                        mapper.Update();<br>
                        session.setAttribute(mapperKey, mapper);<br>
<br>
                        volume = new vtkVolume();<br>
                        volume.SetMapper(mapper);<br>
                        volume.SetProperty(volumeProperty);<br>
                        session.setAttribute(volumeKey, volume);<br>
<br>
                        count = 0;<br>
                        session.setAttribute(countKey, count);<br>
<br>
                        renderer = new vtkRenderer();<br>
                        renderer.AddVolume(volume);<br>
                        session.setAttribute(rendererKey, renderer);<br>
<br>
                        renderWindow = new vtkRenderWindow();<br>
                        renderWindow.SetSize(300, 300);<br>
                        renderWindow.SetOffScreenRendering(1);<br>
                        renderWindow.AddRenderer(renderer);<br>
                        session.setAttribute(renderWindowKey, renderWindow);<br>
<br>
                        interactor = new vtkRenderWindowInteractor();<br>
                        interactor.SetRenderWindow(renderWindow);<br>
                        session.setAttribute(interactorKey, interactor);<br>
<br>
                        interactor.Initialize();<br>
                        interactor.Render();<br>
                } else {<br>
                        interactor =<br>
(vtkRenderWindowInteractor)session.getAttribute(interactorKey);<br>
                        renderWindow = (vtkRenderWindow)session.getAttribute(renderWindowKey);<br>
<br>
                        count = (int)session.getAttribute(countKey);<br>
                        count++;<br>
                        if (count == 1) {<br>
                                interactor.SetEventPosition(100, 100);<br>
                                interactor.SetLastEventPosition(100, 100);<br>
                                interactor.LeftButtonPressEvent();<br>
                                interactor.LeftButtonReleaseEvent();<br>
                        }<br>
                        else {<br>
                                interactor.LeftButtonPressEvent();<br>
                                interactor.SetEventPosition(110, 110);<br>
                                interactor.SetLastEventPosition(100, 100);<br>
                                interactor.MouseMoveEvent();<br>
                                interactor.LeftButtonReleaseEvent();<br>
                        }<br>
                        session.setAttribute(countKey, count);<br>
                }<br>
<br>
                int[] size = renderWindow.GetSize();<br>
<br>
                vtkUnsignedCharArray pixelDataArray = new vtkUnsignedCharArray();<br>
<br>
                renderWindow.GetPixelData(0, 0, size[0] - 1, size[1] - 1,<br>
                                1-renderWindow.GetDoubleBuffer(), pixelDataArray);<br>
<br>
                // convert unsigned char to byte,note the range of each primitive type<br>
                byte[] bytePixelData = pixelDataArray.GetJavaArray();<br>
<br>
                int[] RGBPixelData = new int[bytePixelData.length];<br>
<br>
                // convert byte to unsigned and stored in RGBPixelData array<br>
                for (int i = 0; i < RGBPixelData.length; i++) {<br>
                        RGBPixelData[i] = bytePixelData[i] & 0xff;<br>
                }<br>
                int[] pixelData = new int[size[0] * size[1]];<br>
<br>
                int index = 0;<br>
                int r, g, b;<br>
<br>
                // The sequence of pixels is from left to right and from bottom to top,<br>
                // so we need flip the RGB pixel<br>
                // no A channel to avoid image distortion<br>
                for (int row = size[1] - 1; row >= 0; row--) {<br>
                        for (int column = 0; column < size[0]; column++) {<br>
                                r = RGBPixelData[3 * (size[1] * row + column)];<br>
                                g = RGBPixelData[3 * (size[1] * row + column) + 1];<br>
                                b = RGBPixelData[3 * (size[1] * row + column) + 2];<br>
<br>
                                if (r > 255) {<br>
                                        r = 255;<br>
                                }<br>
                                if (r < 0) {<br>
                                        r = 0;<br>
                                }<br>
                                if (g > 255) {<br>
                                        g = 255;<br>
                                }<br>
                                if (g < 0) {<br>
                                        g = 0;<br>
                                }<br>
                                if (b > 255) {<br>
                                        b = 255;<br>
                                }<br>
                                if (b < 0) {<br>
                                        b = 0;<br>
                                }<br>
<br>
                                pixelData[index] = ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b &<br>
0xff));<br>
                                index++;<br>
                        }<br>
<br>
                }<br>
                BufferedImage bi = new BufferedImage(size[0], size[1],<br>
                                BufferedImage.TYPE_INT_RGB);<br>
                bi.getRaster().setDataElements(0, 0, size[0], size[1], pixelData);<br>
<br>
                // get a ServletOutputStream for writing binary data<br>
                ServletOutputStream so = resp.getOutputStream();<br>
                // This creates an instance of a JPEGImageEncoder<br>
                // that can be used to encode image data as JPEG Data streams.<br>
                JPEGImageEncoder jie = JPEGCodec.createJPEGEncoder(so);<br>
                // Encode a BufferedImage as a JPEG data stream<br>
                jie.encode(bi);<br>
<br>
                so.flush();<br>
        }<br>
<br>
<br>
}<br>
<br>
The first request still can get the image, but the second request failed.<br>
After some debugging works, I hav found that the problem happeneded at the<br>
interactor.MouseMoveEvent() method which invokes the<br>
vtkRenderWindowInteractor::Render() method. I don't know why it crashed at<br>
this place.  Is there something wrong with my java servlet code? I have been<br>
confused with this problem for several months.<br>
Looking forward to your reply!<br>
Best fishes!<br>
<br>
<br>
<br>
<br>
--<br>
View this message in context: <a href="http://vtk.1045678.n5.nabble.com/Java-servlet-Glassfish-volume-rendering-applications-problem-tp5730017p5730190.html" target="_blank">http://vtk.1045678.n5.nabble.com/Java-servlet-Glassfish-volume-rendering-applications-problem-tp5730017p5730190.html</a><br>
<div class="HOEnZb"><div class="h5">Sent from the VTK - Users mailing list archive at Nabble.com.<br>
_______________________________________________<br>
Powered by <a href="http://www.kitware.com" target="_blank">www.kitware.com</a><br>
<br>
Visit other Kitware open-source projects at <a href="http://www.kitware.com/opensource/opensource.html" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
<br>
Please keep messages on-topic and check the VTK FAQ at: <a href="http://www.vtk.org/Wiki/VTK_FAQ" target="_blank">http://www.vtk.org/Wiki/VTK_FAQ</a><br>
<br>
Search the list archives at: <a href="http://markmail.org/search/?q=vtkusers" target="_blank">http://markmail.org/search/?q=vtkusers</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="http://public.kitware.com/mailman/listinfo/vtkusers" target="_blank">http://public.kitware.com/mailman/listinfo/vtkusers</a><br>
</div></div></blockquote></div><br></div>