2

i am trying to create a multiframe dicom file from multiple JPEG file by writing them using Imagewriter but writer.canWriteSequence() is always giving false so not able to write jpeg file to the multiframe dicom file so is there any way i can create the multiframe dicom file from jpeg image or bufferedimage

 public Attributes createDicomHeader(BufferedImage sampleFrame, int numberOfFrames) {

        // Get some image information from the sample image:
        // All frames should have the same information so we will get it only once.

     int colorComponents = sampleFrame.getColorModel().getNumColorComponents();
        int bitsPerPixel = sampleFrame.getColorModel().getPixelSize();
        int bitsAllocated = (bitsPerPixel / colorComponents);
        int samplesPerPixel = colorComponents;

        // The DICOM object that will hold our frames
        Attributes dicom = new Attributes();

        // Add patient related information to the DICOM dataset
        dicom.getString(Tag.PatientName, "Aditya^G");
        dicom.getString(Tag.PatientID, "1234ID");
        dicom.getDate(Tag.PatientBirthDate, new java.util.Date());
        dicom.getString(Tag.PatientSex, "M");

        // Add study related information to the DICOM dataset
        dicom.getString(Tag.AccessionNumber, "1234AC");
        dicom.getString(Tag.StudyID, "1");
        dicom.getString(Tag.StudyDescription, "MULTIFRAME STUDY");
        dicom.setDate(Tag.StudyDate, new java.util.Date());
        dicom.setDate(Tag.StudyTime, new java.util.Date());

        // Add series related information to the DICOM dataset
        dicom.setInt(Tag.SeriesNumber,VR.US, 1);
        dicom.setDate(Tag.SeriesDate, new java.util.Date());
        dicom.setDate(Tag.SeriesTime, new java.util.Date());
        dicom.getString(Tag.SeriesDescription, "MULTIFRAME SERIES");
        dicom.getString(Tag.Modality, "SC"); // secondary capture

        // Add image related information to the DICOM dataset
        dicom.setInt(Tag.InstanceNumber, VR.US, 1);
        dicom.setInt(Tag.SamplesPerPixel, VR.US, samplesPerPixel);
        dicom.setString(Tag.PhotometricInterpretation, VR.CS, "YBR_FULL_422");
        dicom.setInt(Tag.Rows, VR.US, sampleFrame.getHeight());
        dicom.setInt(Tag.Columns, VR.US, sampleFrame.getWidth());
        dicom.setInt(Tag.BitsAllocated, VR.US, bitsAllocated);
        dicom.setInt(Tag.BitsStored, VR.US, bitsAllocated);
        dicom.setInt(Tag.HighBit, VR.US, bitsAllocated-1);
        dicom.setInt(Tag.PixelRepresentation, VR.US, 0);

        // Add the unique identifiers
        dicom.setString(Tag.SOPClassUID, VR.UI, UID.SecondaryCaptureImageStorage);
        dicom.setString(Tag.StudyInstanceUID, VR.UI, UIDUtils.createUID());
        dicom.setString(Tag.SeriesInstanceUID, VR.UI, UIDUtils.createUID());
        dicom.setString(Tag.SOPInstanceUID, VR.UI, UIDUtils.createUID());

        //Start of multiframe information:
        dicom.setInt(Tag.StartTrim, VR.US, 1);                   
        dicom.setInt(Tag.StopTrim, VR.US, numberOfFrames);     
        dicom.getString(Tag.FrameTime, 0, "33.33");         
        dicom.getString(Tag.FrameDelay, "0.0");           
        dicom.setInt(Tag.NumberOfFrames, VR.US, numberOfFrames); // The number of frames
        dicom.setInt(Tag.RecommendedDisplayFrameRate, VR.US, 3);  
        dicom.setInt(Tag.FrameIncrementPointer, VR.US, Tag.FrameTime);
        //End of multiframe information.

        // Add the default character set
        dicom.setString(Tag.SpecificCharacterSet, VR.CS, "ISO_IR 100");

        // Init the meta information with JPEG Lossless transfer syntax
        dicom.createFileMetaInformation(UID.JPEGBaseline1);

        return dicom;
    }


     public void encodeMultiframe(File[] frames, File dest) 
     throws IOException {
        // Status message
        System.out.println("Creating Multiframe File...");

        // Create DICOM image writer instance and set its output

        ImageReadParam dicomr=new DicomImageReadParam();
        ImageWriter writer =  ImageWriterFactory.getImageWriter(ImageWriterFactory.getImageWriterParam(UID.JPEGBaseline1));

        FileImageOutputStream output = new FileImageOutputStream(dest);
        writer.setOutput(output);

        // Get an image sample from the array of images
        BufferedImage sample = ImageIO.read(frames[0]);

        // Create a new dataset (header/metadata) for our DICOM image writer
        Attributes ds = this.createDicomHeader(sample, frames.length);
        Attributes fmi = ds.createFileMetaInformation(UID.JPEGBaseline1);
        // Set the metadata to our DICOM image writer and prepare to encode the multiframe sequence
     //  ImageWriteParam iwp= writer.getDefaultWriteParam() ;
       DicomMetaData writeMeta = new DicomMetaData(fmi, ds);
        writeMeta.getAttributes().addAll(ds);

        if(writer.canWriteSequence())
        writer.prepareWriteSequence(writeMeta);

        else
            System.out.println("can not write to sequence");


        // DicomMetaData writeMeta = (DicomMetaData) writer.getDefaultStreamMetadata(null);
     //   writeMeta.getAttributes().addAll(ds);
     //   writer.prepareWriteSequence(writeMeta);







        // Status message
        System.out.println("Start of Write Sequence...");

        // For each extracted JPEG images...
        for (int i = 0; i < frames.length; i++) {

            // Status message
            System.out.println("Encoding frame # "+ (i+1));

            // Read the JPEG file to a BufferedImage object
            BufferedImage frame = ImageIO.read(frames[i]);

            // Create a new IIOImage to be saved to the DICOM multiframe sequence
            IIOImage iioimage = new IIOImage(frame, null, null);

            // Write our image to the DICOM multiframe sequence
            writer.writeToSequence(iioimage, null);
        }

        // Status message
        System.out.println("End of Write Sequence.");

        // Our multiframe file was created. End the sequence and close the output stream.
        writer.endWriteSequence();
        output.close();

        // Status message
        System.out.println("Multiframe File Created.");
    }

/**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {
    MultiframeImageCreation mf=new MultiframeImageCreation();


    File[] frames = new File("/root/Desktop/multi").listFiles();

    // Create the DICOM multiframe file
    mf.encodeMultiframe(frames, new File("/root/Desktop/multiframe.dcm"));

}

}

aditya gupta
  • 403
  • 2
  • 10

1 Answers1

0

Try to use this code

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

import org.dcm4che2.data.BasicDicomObject;
import org.dcm4che2.data.DicomObject;
import org.dcm4che2.data.Tag;
import org.dcm4che2.data.UID;
import org.dcm4che2.data.VR;
import org.dcm4che2.imageio.plugins.dcm.DicomStreamMetaData;
import org.dcm4che2.imageioimpl.plugins.dcm.DicomImageWriterSpi;
import org.dcm4che2.util.UIDUtils;

public class Mpeg2Dicom {

    public Mpeg2Dicom() {

    }

    public DicomObject createDicomHeader(BufferedImage sampleFrame, int numberOfFrames) {
        int colorComponents = sampleFrame.getColorModel().getNumColorComponents();
        int bitsPerPixel = sampleFrame.getColorModel().getPixelSize();
        int bitsAllocated = (bitsPerPixel / colorComponents);
        int samplesPerPixel = colorComponents;
        // The DICOM object that will hold our frames
        DicomObject dicom = new BasicDicomObject();
        // Add patient related information to the DICOM dataset
        dicom.putString(Tag.PatientName, null, "Patient Name");
        dicom.putString(Tag.PatientID, null, "1234ID");
        dicom.putDate(Tag.PatientBirthDate, null, new java.util.Date());
        dicom.putString(Tag.PatientSex, null, "M");
        // Add study related information to the DICOM dataset
        dicom.putString(Tag.AccessionNumber, null, "1234AC");
        dicom.putString(Tag.StudyID, null, "1");
        dicom.putString(Tag.StudyDescription, null, "MULTIFRAME STUDY");
        dicom.putDate(Tag.StudyDate, null, new java.util.Date());
        dicom.putDate(Tag.StudyTime, null, new java.util.Date());
        // Add series related information to the DICOM dataset
        dicom.putInt(Tag.SeriesNumber, null, 1);
        dicom.putDate(Tag.SeriesDate, null, new java.util.Date());
        dicom.putDate(Tag.SeriesTime, null, new java.util.Date());
        dicom.putString(Tag.SeriesDescription, null, "MULTIFRAME SERIES");
        dicom.putString(Tag.Modality, null, "SC"); // secondary capture
        // Add image related information to the DICOM dataset
        dicom.putInt(Tag.InstanceNumber, null, 1);
        dicom.putInt(Tag.SamplesPerPixel, null, samplesPerPixel);
        dicom.putString(Tag.PhotometricInterpretation, VR.CS, "YBR_FULL_422");
        dicom.putInt(Tag.Rows, null, sampleFrame.getHeight());
        dicom.putInt(Tag.Columns, null, sampleFrame.getWidth());
        dicom.putInt(Tag.BitsAllocated, null, bitsAllocated);
        dicom.putInt(Tag.BitsStored, null, bitsAllocated);
        dicom.putInt(Tag.HighBit, null, bitsAllocated-1);
        dicom.putInt(Tag.PixelRepresentation, null, 0);
       // Add the unique identifiers
        dicom.putString(Tag.SOPClassUID, null, UID.SecondaryCaptureImageStorage);
        dicom.putString(Tag.StudyInstanceUID, null, UIDUtils.createUID());
        dicom.putString(Tag.SeriesInstanceUID, null, UIDUtils.createUID());
        dicom.putString(Tag.SOPInstanceUID, VR.UI, UIDUtils.createUID());
        //Start of multiframe information:
        dicom.putInt(Tag.StartTrim, null, 1);                   // Start at frame 1
        dicom.putInt(Tag.StopTrim, null, numberOfFrames);       // Stop at frame N
        dicom.putString(Tag.FrameTime, null, "33.33");          // Milliseconds (30 frames per second)
        dicom.putString(Tag.FrameDelay, null, "0.0");           // No frame dalay
        dicom.putInt(Tag.NumberOfFrames, null, numberOfFrames); // The number of frames
        dicom.putInt(Tag.RecommendedDisplayFrameRate, null, 3); 
        dicom.putInt(Tag.FrameIncrementPointer, null, Tag.FrameTime);
        //End of multiframe information.
        // Add the default character set
        dicom.putString(Tag.SpecificCharacterSet, VR.CS, "ISO_IR 100");
        // Init the meta information with JPEG Lossless transfer syntax
       // dicom.initFileMetaInformation(UID.JPEGLossless);
        dicom.initFileMetaInformation(UID.JPEGBaseline1);
        return dicom;
    }


     public void encodeMultiframe(File[] frames, File dest) throws IOException {
        // Status message
        System.out.println("Creating Multiframe File...");
        // Create DICOM image writer instance and set its output
        ImageWriter writer = new DicomImageWriterSpi().createWriterInstance();
        FileImageOutputStream output = new FileImageOutputStream(dest);
        writer.setOutput(output);
        // Get an image sample from the array of images
        BufferedImage sample = ImageIO.read(frames[0]);
        // Create a new dataset (header/metadata) for our DICOM image writer
        DicomObject ds = this.createDicomHeader(sample, frames.length);
        // Set the metadata to our DICOM image writer and prepare to encode the multiframe sequence
        DicomStreamMetaData writeMeta = (DicomStreamMetaData) writer.getDefaultStreamMetadata(null);
        writeMeta.setDicomObject(ds);
        writer.prepareWriteSequence(writeMeta);

        System.out.println("Start of Write Sequence...");

        for (int i = 0; i < frames.length; i++) {
            // Status message
            System.out.println("Encoding frame # "+ (i+1));
            // Read the PNG file to a BufferedImage object
            BufferedImage frame = ImageIO.read(frames[i]);
            // Create a new IIOImage to be saved to the DICOM multiframe sequence
            IIOImage iioimage = new IIOImage(frame, null, null);
            // Write our image to the DICOM multiframe sequence
            writer.writeToSequence(iioimage, null);
        }
        // Status message
        System.out.println("End of Write Sequence.");
        // Our multiframe file was created. End the sequence and close the output stream.
        writer.endWriteSequence();
        output.close();
        // Status message
        System.out.println("Multiframe File Created.");
    }

    public static void main(String[] args) { 
        try {
            // Create an instance of our class
            Mpeg2Dicom f = new Mpeg2Dicom();

            // Create the array of files for the extracted FFMPEG images
            File[] frames = new File("d://AAA").listFiles();

            // Create the DICOM multiframe file
            f.encodeMultiframe(frames, new File("d:///multiframe.dcm"));

        } catch (Exception e) {
            // Print exceptions
            e.printStackTrace();
        }
    }
}

Before run this code please install Java Advanced Imaging Image I/O Tools 32 Bit version 1.0_01 Java Advanced Imaging Image and also try to run this code using Java 32 Bit version

  • a) JAI ImageIO library is not installed;
  • b) JAI ImageIO is installed but has no values set in the PATH environment variable;
  • c) DLL files with JAI native code cannot be found (wrong installation);
  • d) Your Windows is 64bits (it will work only for Win32);
Panchotiya Vipul
  • 1,226
  • 5
  • 17
  • 42
  • I got this same code from here http://samucs.blogspot.com/2011/02/creating-dicom-multiframe-files-mpeg-to.html. I was able to create a DICOM image with multiple JPEG images but output DICOM image is not opening into MicroDicom viewer so it seems it is getting something wrong or getting corrupted. Any tip on how to create correct DICOM image. – Prakash Boda Jun 15 '23 at 04:51
  • If you are trying to open converted file into viewer and it gives error that it can not open file then most probably you are missing Planar Configuration tag which is required if Samples per pixel is more than 1. You can refer to below DICOM specification. https://dicom.innolitics.com/ciods/enhanced-mr-image/enhanced-mr-image/00280006 – Prakash Boda Jun 23 '23 at 03:40