The SplitMultiframeImage example demonstrates how to use DCF to split a multiframe image into a series of single frame datasets.
Classes
Class | Description | |
---|---|---|
Options |
Command line options class for parsing user options for SplitMultiframeImage
| |
Program |
Shows how to read a multiframe images and split it into individual frames.
|
Remarks
Supported OS Platforms:
- Windows - .Net Framework 4.7.2 64-bit and 32-bit
- Windows - .Net Core 2.1 64-bit and 32-bit
- Linux - .Net Core 2.1 64-bit
Examples
SplitMultiframeImage Sample Code
public class Program { private static readonly ILogger Logger = LogManager.GetCurrentClassLogger(); /// <summary> /// Main entry point for SplitMultiframeImage. /// </summary> /// <param name="args">command line arguments</param> [STAThread] private static void Main(string[] args) { try { Options options; if (!Options.TryParse(args, out options)) { throw new ArgumentException("bad command line parameters"); } DicomSessionSettings sessionSettings = new DicomSessionSettings(); sessionSettings.EnableStreamingMode = true; // turn off large element handling to avoid problems with reading elements multiple times sessionSettings.LargeElementThreshold = 0; DicomFileInput dfi = new DicomFileInput(options.InputFileName, sessionSettings); dfi.Open(); DicomDataSet ds = dfi.ReadDataSet(); dfi.Close(); DicomStreamableDataElement pixelElement = ds.GetElement(Tags.PixelData) as DicomStreamableDataElement; if (pixelElement != null) { string sopInstanceUid = ds.GetElementStringValue(Tags.SOPInstanceUID); ImageInfo imageInfo = new ImageInfo(ds); ds.RemoveElement(Tags.PixelData); pixelElement.Producer.BeginStreamingModeTransfer(); // create a buffer which we'll reuse // // *** account for odd frame sizes, which are legal in a // multi-frame data set, but not as the pixel element // length for the to-be-created single frame data sets. // We'll create the buffer with the pad byte, but then // set the limit to one less so the read() fetches the // correct size. After the read, we move the limit back // up by one so the element ctor sees the even length. // int frameSize = imageInfo.FrameSize; int bufferSize = ((frameSize & 1) == 0) ? frameSize : frameSize + 1; ByteBuffer buf = ByteBuffer.Allocate(bufferSize); // change frame count for all data sets ds.Insert(new DicomISElement(Tags.NumberOfFrames, "1")); // we probably should change some other things // in the new data-set, e.g., maybe the sop-instance-uid // and perhaps set type to DERIVED and add // a derivation-description or something that says // where the image came from... int fieldLength = imageInfo.NumberOfFrames.ToString().Length; string fmt = "{0}.{1," + fieldLength + ":D" + fieldLength + "}.dcm"; if (!Directory.Exists(options.OutputDirectory)) { Directory.CreateDirectory(options.OutputDirectory); } string baseName = Path.GetFileNameWithoutExtension(options.InputFileName); for (int i = 0; i < imageInfo.NumberOfFrames; i++) { // create new sop instance uid by appending frame number to sopInstanceUid String newSopInstanceUid = sopInstanceUid + "." + i; String outputFileName = Path.Combine(options.OutputDirectory, String.Format(fmt, baseName, i)); // do this each time, since we're reusing the // buffer as we save the individual frames. buf.Limit = frameSize; int count = pixelElement.Producer.GetBuf(buf); if (count != imageInfo.FrameSize) { throw new DCSException("failed to read frame data"); } // set the limit to count the pad byte. buf.Limit = bufferSize; DicomStreamableDataElement frameDataElement; if (pixelElement is DicomOWElement) { frameDataElement = new DicomOWElement(Tags.PixelData, buf); } else { frameDataElement = new DicomOBElement(Tags.PixelData, buf); } // keep overwriting the pixel element with the pixels for the // current frame and the sop instance uid ds.Insert(frameDataElement); DicomUIElement instanceUid = new DicomUIElement(Tags.SOPInstanceUID, newSopInstanceUid); DicomUIElement mediaStorageInstanceUid = new DicomUIElement(Tags.MediaStorageSOPInstanceUID, newSopInstanceUid); ds.Insert(instanceUid); if (ds.ContainsElement(Tags.MediaStorageSOPInstanceUID)) { ds.Insert(mediaStorageInstanceUid); } DicomFileOutput dfo = new DicomFileOutput(outputFileName, options.OutputTransferSyntax, sessionSettings); dfo.Open(); dfo.WriteDataSet(ds); dfo.Close(); } DicomDataSet trailingElements = pixelElement.Producer.EndStreamingModeTransfer(); if (trailingElements.Count > 0) { Logger.Warn("multi-frame data set had elements following pixel data which were ignored"); } } else { Logger.Error("no pixels to split"); } } catch (Exception e) { Logger.Error(e, "Exception:"); Environment.ExitCode = 1; } finally { if (System.Diagnostics.Debugger.IsAttached) { Console.Write("Press any key to continue . . . "); Console.ReadKey(); } } } }