Wednesday, January 6, 2010

DICOM Multiframe playback using dcm4che 2

Hello visitors,

First of all I'd like to thank you all for every email, tips, comments and mainly the valuable knowledge we have been sharing since I started this simple blog. This time I want to write a tutorial that takes a multiframe DICOM image and then playback it frame by frame. The final result is a Swing Java application where we can watch such file as it was a video file. If you feel it sounds nice so let's go!

If it's your first time here, please I strongly recommend that you read my DICOM to JPEG Conversion post so you can learn how to setup Eclipse and dcm4che toolkit. Then come back to this post and continue to this example tutorial. Let's start! Open your Eclipse IDE and choose File > New > Java Project. Name it DicomExamples. The next step is to create a new class, so right-click the src package and select New > Class. Enter DicomMultiframePlayer for class name and select the main method option. You'll get something like this:

public class DicomMultiframePlayer {  
   public static void main(String[] args) {  
      // TODO Auto-generated method stub  
   }   
}  

To make this tutorial easy to understand I will first build the Java Swing Graphic User Interface (GUI). In order to get a Java Swing application our class must be a JFrame class instance. Then since it's a Desktop program we need to provide some interaction to the user. We can do this by creating some JButton components where the user can open and playback the DICOM file. Thus, we should think how to control the playback, here we will use a specific Java Thread. Finally to accomplish all these requirements we must change our code a little.

public class DicomMultiframePlayer extends JFrame 
implements ActionListener, Runnable {

   /**
    * Class constructor.
    */
   public DicomMultiframePlayer() {
      // TODO Auto-generated method stub   
   }

   /**
    * This class implements the Runnable interface.
    * It will handle thread execution.
    */
   @Override
   public void run() {
      // TODO Auto-generated method stub  
   }

   /**
    * This class implements the ActionListener interface.
    * It will handle action events performed by buttons.
    * @param e ActionEvent object source. 
    */
   @Override
   public void actionPerformed(ActionEvent e) {
      // TODO Auto-generated method stub  
   }

   /**
    * This is a private class to render images onto a JPanel component.
    */
   private class ImagePanel extends JPanel {
      // TODO Auto-generated method stub     
   };

   /**
    * Run the program.
    * @param args Program arguments.
    */
   public static void main(String[] args) {  
      new DicomMultiframePlayer();
   }   
}  

As you can see our simple class now has additional Java interfaces implementations: ActionListener and Runnable. The first will handle JButton actions and the second handles Java thread execution. Also, I started to code a private class that will be responsible for rendering our images onto a JPanel component. For now our GUI class needs some Swing components and new class attributes, so let's declare them.

   // These Swing components will be our file chooser
   private JLabel fileLabel;
   private JTextField fileField;
   private JButton btnChoose;

   // These Swing components will be our playback controls
   private JButton btnPlay;
   private JButton btnPause;
   private JButton btnStop;
   private JButton btnExit;

   // This vector stores all image frames for playback 
   private Vector<BufferedImage> images;

   // This is a Swing JPanel control for image display 
   private ImagePanel imagePanel;

   // Used for simple playback control 
   private boolean stop;
   private int currentFrame;

The next step is to instantiate evey class attribute inside the class constructor. But before that let's code a helper method for JButton creation. Since we have more than 3 buttons it's useful to code a creation method, this way we save several lines of code. I called this method createJButton().

   /**
    * Create a new Java Swing JButton.
    * @param width button width.
    * @param height button height.
    * @param text button text.
    * @return a new JButton.
    */
   private JButton createJButton(int width, int height, String text) {
      JButton b = new JButton(text);
      b.setMinimumSize(new Dimension(width, height));
      b.setMaximumSize(new Dimension(width, height));
      b.setPreferredSize(new Dimension(width, height));
      
      // button action will be handled by 'this' class 
      b.addActionListener(this);
      return b;
   }

Then let's instantiate our class members and attributes inside the class constructor as follows:

   // Call the parent constructor and pass the window frame title.
   // Tell the application to terminate when the user close the window.
   // Configure a new BorderLyout for our application frame.
   super("XA Player using dcm4che - by samucs-dev");
   this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   this.getContentPane().setLayout(new BorderLayout());

   // Initialize our frame vector.
   // Create our panel to render Dicom images.
   images = new Vector<BufferedImage>();
   imagePanel = new ImagePanel();

   // Configure the file chooser component.
   fileLabel = new JLabel("File:");
   fileField = new JTextField(30);
   btnChoose = this.createJButton(25, 25, "...");
  
   // Configure our JButton components for playback control.
   btnPlay = this.createJButton(80,25,"Play");
   btnPause = this.createJButton(80,25,"Pause");
   btnStop = this.createJButton(80,25,"Stop");  
   btnExit = this.createJButton(80,25,"Exit");
   btnPause.setEnabled(false);
   btnStop.setEnabled(false);
 
   // Add the file chooser to the top of the frame window.
   JPanel panelNorth = new JPanel();
   panelNorth.add(fileLabel);
   panelNorth.add(fileField);
   panelNorth.add(btnChoose);
   this.getContentPane().add(panelNorth, BorderLayout.NORTH);

   // Add the image render panel to the center of the frame window.
   this.getContentPane().add(imagePanel, BorderLayout.CENTER);

   // Add the buttons to the bottom of the frame window.
   JPanel panelSouth = new JPanel();
   panelSouth.add(btnPlay);
   panelSouth.add(btnPause);
   panelSouth.add(btnStop);
   panelSouth.add(btnExit);  
   this.getContentPane().add(panelSouth, BorderLayout.SOUTH);  

   // Configure frame window size and then show it.
   this.setSize(new Dimension(500,500));
   this.setLocationRelativeTo(null);
   this.setVisible(true);

Well, that was a lot of code. Don't be afraind this is Java GUI done by hand :) Your reward to get here is to execute the program and see your great job! Right click the DicomMultiframePlayer class and choose Run As > Java Application. You will see something like the picture below.



The GUI is almost done. Now we must implement the ImagePanel class. This is a key part for us to playback the multiframe Dicom file. The ImagePanel class extends the Swing JPanel component. This way we can use its paint() method for rendering our images and then display it to the user through the main GUI. We have to implement it as a private class for our application as follows:

   private class ImagePanel extends JPanel {
      // The image to be rendered onto the panel. */
      private BufferedImage image;
      // Class constructor. */
      public ImagePanel() {
         super();
         this.setPreferredSize(new Dimension(1024,1024));
         this.setBackground(Color.black);   
      }
      // Set the image to be rendered. */
      public void setImage(BufferedImage image) {
         this.image = image;
         this.updateUI();
      }
      // Render the image. */
      @Override
      public void paint(Graphics g) {
         if (this.image != null) {
            g.drawImage(this.image, 0, 0, image.getWidth(), image.getHeight(), null);
         }
      }
   };

That's it! Our GUI is done! Now all we have to do is to code a method for opening our DICOM file and implement the ActionListener and Runnable interfaces. First let's see how openFile() method shoulde be. That's where we use the amazing dcm4che toolkit for extracting DICOM image frames.

   private void openFile(File file) {
      // Clear the image vector */
      images.clear();
      try {
         // Here we get a new image reader for our Dicom file. */
         System.out.println("Reading DICOM image...");   
         ImageReader reader = new DicomImageReaderSpi().createReaderInstance();
         FileImageInputStream input = new FileImageInputStream(file);
         reader.setInput(input);

         // Just to show the number of frames. */
         int numFrames = reader.getNumImages(true);
         System.out.println("DICOM image has "+ numFrames +" frames...");
 
         // For each frame we read its image and then add it to the image vector. */
         System.out.println("Extracting frames...");
         for (int i=0; i < numFrames; i++) {
            BufferedImage img = reader.read(i);
            images.add(img);
            System.out.println(" > Frame "+ (i+1));
         }   
         // That's it we read all frames. */
         System.out.println("Finished.");
      } catch(Exception e) {
         e.printStackTrace();
         imagePanel.setImage(null);
         return;
      }
      // This is the first playback control. 
      // After reading we always display the first frame. */
      stop = false;
      currentFrame = 0;
      imagePanel.setImage(images.get(0));
   }

Now the actionPerformed() method implemented from the ActionListener interface handles all action events from our control buttons. The code below shows how this should be. See that depending on the button that was pressed other buttons become disabled. This is just to certify the final user will use the GUI properly.

   @Override
   public void actionPerformed(ActionEvent e) {  
      // The user is opening a file. */
      if (e.getSource().equals(btnChoose)) {
         JFileChooser chooser = new JFileChooser();
         int action = chooser.showOpenDialog(this);
         switch(action) {
            case JFileChooser.APPROVE_OPTION:
               this.openFile(chooser.getSelectedFile());
               break;
            case JFileChooser.CANCEL_OPTION:
               return; 
         }
      }  
      // Start playback of Dicom frames. */
      if (e.getSource().equals(btnPlay)) {
         btnPlay.setEnabled(false);
         btnPause.setEnabled(true);
         btnStop.setEnabled(true);
         stop = false;
         new Thread(this).start();   
      }
      // Pause playback. */
      if (e.getSource().equals(btnPause)) {
         btnPlay.setEnabled(true);
         btnPause.setEnabled(false);
         btnStop.setEnabled(true);
         stop = false;
      }
      // Stop. Return to the first frame (0). */
      if (e.getSource().equals(btnStop)) {
         btnPlay.setEnabled(true);
         btnPause.setEnabled(false);
         btnStop.setEnabled(false);
         stop = true;
         currentFrame = 0;
         imagePanel.setImage(images.get(0));   
      }
      // Exit the application. */
      if (e.getSource().equals(btnExit)) {
         System.exit(0);
      }
   }

Finally we have the implementation of Runnable interface through the run() method. That's where we handle the playback and give the user the illusion of watching a video file. The run() method is an infinite loop and it is always checking if it has to stop. If the stop flag is false so it increments the frame number and update the display image causing the application to playback the DICOM file.

   @Override
   public void run() {
      while(true) {
         if (!btnPlay.isEnabled()) {    
            // Check if it has to stop. */
            if (stop) break;    
            // Increment the current frame and update the display image. */
            currentFrame++;
            if (currentFrame == images.size())
               currentFrame = 0;
            imagePanel.setImage(
               images.get(currentFrame));    
            // Cause our thread to sleep 70 milliseconds. */
            // Increase this value to slow playback speed. */
            1try {
               Thread.sleep(70);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
         }
      }
   }

Mission accomplished! I hope you have enjoyed all this tutorial. This is a simple application and I expect you to develop it as you wish. Please, get the complete source code and an example multiframe DICOM image to test yourself. Many thanks to Marcio Colunas from University of Aveiro, Portugal, who gave me the permission to use the multiframe image. See you on the next post!

Kinldy regards,

Samuel.

20 comments:

Anonymous said...

hallo; when i compile the programm of DicomMultiframePlayer I get an 2 error:
C:\Program Files\Xinox Software\JCreatorV4\MyProjects\DicomMultiframePlayer\src\DicomMultiframePlayer.java:34: expected
private Vector images;
^
C:\Program Files\Xinox Software\JCreatorV4\MyProjects\DicomMultiframePlayer\src\DicomMultiframePlayer.java:44: '(' or '[' expected
images = new Vector ();
^
2 errors
how Resolve this errors?

Unknown said...

Hello,

Thanks for visiting!

The source code is ok. Be sure you are using the latest JAVA version 6. Maybe your version does not understand "Generics" for Vector objects.

Regards,

Samuel.

Anonymous said...

i am try java version 6 the build and run of source code is ok but the picture of dicom does't displayed why?

Unknown said...

Hi,

Please, be sure you have "dcm4che-image" libraries. Also you need JAI Imageio (https://jai-imageio.dev.java.net) in your Java build path to work with Dicom images using dcm4che.

Regards,

Samuel.

Anonymous said...

i am sure
IDE get:
Reading DICOM image...
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: com/sun/media/imageio/stream/StreamSegmentMapper
at org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReaderSpi.createReaderInstance(DicomImageReaderSpi.java:146)
at javax.imageio.spi.ImageReaderSpi.createReaderInstance(ImageReaderSpi.java:296)
at DicomMultiframePlayer.openFile(DicomMultiframePlayer.java:146)
at DicomMultiframePlayer.actionPerformed(DicomMultiframePlayer.java:101)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6038)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3260)
at java.awt.Component.processEvent(Component.java:5803)
at java.awt.Container.processEvent(Container.java:2058)
at java.awt.Component.dispatchEventImpl(Component.java:4410)
at java.awt.Container.dispatchEventImpl(Container.java:2116)
at java.awt.Component.dispatchEvent(Component.java:4240)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4322)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3986)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3916)
at java.awt.Container.dispatchEventImpl(Container.java:2102)
at java.awt.Window.dispatchEventImpl(Window.java:2429)
at java.awt.Component.dispatchEvent(Component.java:4240)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

Process completed.

Unknown said...

Hello,

This message "java.lang.NoClassDefFoundError" says that the program could not find your imageio classes. You need to add the following to you Java build path:

dcm4che-image-2.0.20.jar
dcm4che-imageio-2.0.20.jar
dcm4che-imageio-rle-2.0.20.jar
clibwrapper_jiio.jar
jai_imageio.jar

Also, don't forget to add the others dcm4che core libraries.

Regards,

Samuel.

Anonymous said...

Hi,
This is great work. Can I use this module in MATLAB. We can call routines of DCM4CHE from MATLAB.
If you have any idea please help me...

Thanks

Anonymous said...

Hi,
I am Sorry, but I got following errors.

java.lang.NoClassDefFoundError: DicomMultiframePlayer
Caused by: java.lang.ClassNotFoundException: DicomMultiframePlayer
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Exception in thread "main"

Unknown said...

Hi Anonymous,

This error falls in java.net package. I believe it's not DicomMultiframePlayer.java error. Are you using applet or something on a network?

Regards,

Samuel.

Anonymous said...

Reading DICOM image...
DICOM image has 76 frames...
Extracting frames...
org.dcm4che2.data.ConfigurationError: No Image Reader of class com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader available for format:jpeg
at org.dcm4che2.imageio.ImageReaderFactory.getReaderForTransferSyntax(ImageReaderFactory.java:99)
at org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReader.initCompressedImageReader(DicomImageReader.java:337)
at org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReader.initImageReader(DicomImageReader.java:322)
at org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReader.read(DicomImageReader.java:484)
at javax.imageio.ImageReader.read(ImageReader.java:923)
at DicomMultiframePlayer.openFile(DicomMultiframePlayer.java:167)
at DicomMultiframePlayer.actionPerformed(DicomMultiframePlayer.java:115)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6267)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6032)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Anonymous said...

hi

while i am executing your code.it show errors like this

Reading DICOM image...
DICOM image has 76 frames...
Extracting frames...
org.dcm4che2.data.ConfigurationError: No Image Reader of class com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader available for format:jpeg
at org.dcm4che2.imageio.ImageReaderFactory.getReaderForTransferSyntax(ImageReaderFactory.java:99)
at org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReader.initCompressedImageReader(DicomImageReader.java:337)
at org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReader.initImageReader(DicomImageReader.java:322)
at org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReader.read(DicomImageReader.java:484)
at javax.imageio.ImageReader.read(ImageReader.java:923)
at DicomMultiframePlayer.openFile(DicomMultiframePlayer.java:167)
at DicomMultiframePlayer.actionPerformed(DicomMultiframePlayer.java:115)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6267)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:6032)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)


help me

Unknown said...

Hello,

Don't forget to install JAI ImageIO package before running this code.

Kindly regards,

Samuel.

VivekKumar said...

Hi i need to convert a mpg video file into dcm file. I'm not able to find a right solution.

Gunter says that he used jpg2dcm Utility :
jpg2dcm --mpeg -C ../etc/jpg2dcm/mpg2dcm.cfg img.mpg video.dcm

But i need to write a program by creating dicom objects with dataset for converting a mpg video file to dcm video file. How to write a program for this as u wrote for JPEG to DICOM and DICOM to JPEG.

Anonymous said...

Great example Samuel, the best in the net, it help me a lot especially the dcm4che libraries integration part... I hope you post an example of sending and receiving images from the server in the future... excellent work

Anonymous said...

But hoe multiframe dcm files can be created?

Anonymous said...

Hi Samuel,

My name's Samuel too. I've been trying to setup samucs-web on my jboss server where I'm also running an instance of dcm4chee. I'm getting the same error when I try to navigate to look at images in a series that others are mentioning about jai but it's unclear to me how to go about installing jai. I believe it's already installed as part of dcm4chee. This is the error I'm getting:

org.dcm4cheri.imageio.plugins.DcmImageReadParamImpl cannot be cast to org.dcm4che2.imageio.plugins.dcm.DicomImageReadParam

Thanks for any help!

Baraa said...

Hello,
Oh my God
that is really very very helpful :)

thank you a lot for your explications

with my best regards Samuel

PG said...

Hi
I have set up the DCM4CHE jars as indicated,
dcm4che-image-2.0.20.jar
dcm4che-imageio-2.0.20.jar
dcm4che-imageio-rle-2.0.20.jar
clibwrapper_jiio.jar
jai_imageio.jar

but the the last 2 jars of 1.1 version . Now the latest 1.1.3 version has these jar's ,
jai_codex.jar, jai_core.jar, mlibwrapper_jai.jar.
I have added the dmc4che jar's to the classpath, but still not able to compile the source.
- pg

Unknown said...

I tried your source code but this is what I got:
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: com/sun/media/imageio/stream/StreamSegmentMapper
at org.dcm4che2.imageioimpl.plugins.dcm.DicomImageReaderSpi.createReaderInstance(DicomImageReaderSpi.java:146)
at javax.imageio.spi.ImageReaderSpi.createReaderInstance(Unknown Source)

I added all the dicom4che2 jar/ and jai imageio.jar

Unknown said...

hii... i tried your code and add all required jar files- image,imageio,jai,core,slf4j,logback-core,logback-classic,clipwraperjii etc. but still i am unable to run successfully these code. and this time i am getting eror like:
Failed to instantiate [ch.qos.logback.classic.LoggerContext]
Reported exception:
java.lang.NoSuchMethodError: ch.qos.logback.classic.util.ContextInitializer.(Lch/qos/logback/classic/LoggerContext;)V
----------------------------******
and also.........
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/dcm4che2/util/GenericNumericArray.
-----------------------------****
and
Caused by: java.lang.ClassNotFoundException: org.dcm4che2.util.GenericNumericArray
and many so please help me how can i fix all these erors and bugs. Thanks in advanced. reply please.