LAUREL BRIDGE

LaurelBridge.DCFExamples.CodecConfiguration Namespace

DICOM Connectivity Framework V3.4
The CodecConfiguration example demonstrates how to configure different codec options in DCF.
Classes

  ClassDescription
Public classProgram
This program will transcode the mr-knee.dcm sample image to Lossy Jpeg2000 (.91) using a legacy Jasper codec configuration.

The alternate codec uses the legacy FracBits=13 Jasper library that is no longer used in DCF because it demonstrated some quality issues for certain types of hi-frequency images.

Codec options may be read from a configuration file at startup, or configured programmatically. It is also possible to independently configure input and output operations independently, on a per session basis using the DicomSessionSettings class.

This example demonstrates how codecs may be configured by creating a derived instance of a DicomTSCodecOptions for the codec in question, reconfiguring properties, and using SetCodecOptions(DicomTSCodecOptions, CodecIOMode) to set the options for the codec during the input or output operation.

In the following example, the DicomFileOutput class will pass its DicomSessionSettings to the DicomTSCodecFactory that constructs the output codec. Note that the same method may be used to customize Codec options for input codecs. Quality and processing options may also be configured in the DicomTSCodecOptions derived classes.

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

CodecConfiguration Sample Code
    public class Program
    {
        private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
        private static string JasperOverridesConfigFilename = "JasperJ2k91.config";

        /// <summary>
        /// Main entry point for CodecConfiguration.
        /// </summary>
        [STAThread]
        public static void Main()
        {
            try
            {
                ConfigureCodecPerSessionSettingsForJasper91();
                ConfigureCodecPerSessionSettingsForOpenJpeg90();
                SaveConfigurationForJasper();
                ApplyOverridesForJasper();
                ChangeJ2KCodecsToOpenJpeg();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception caught during execution: {0}", e);
                Environment.ExitCode = 1;
            }

            if (System.Diagnostics.Debugger.IsAttached)
            {
                Console.Write("Press any key to continue . . . ");
                Console.ReadKey();
            }
        }

        private static void ConfigureCodecPerSessionSettingsForJasper91()
        {
            string imagePath = "mr-knee.dcm";
            string outputImagePath = "mr-knee-jasper91-compressed.dcm";
            string outputUid = Uids.J2k91;

            JasperCodecOptions jasperOptions = new JasperCodecOptions(outputUid);
            jasperOptions.WinDllBaseName = "DCF_TSCWJasper13";
            jasperOptions.UnixDllBaseName = "DCF_TSCWJasper13";
            DicomSessionSettings sessionSettings = new DicomSessionSettings();
            sessionSettings.SetCodecOptions(jasperOptions);

            using (DicomFileInput dfi = new DicomFileInput(imagePath))
            {
                DicomDataSet ds = dfi.ReadDataSet();
                using (DicomFileOutput dfo = new DicomFileOutput(outputImagePath, outputUid, sessionSettings))
                {
                    dfo.WriteDataSet(ds);
                    Console.WriteLine("Image ({0}) compressed successfully using ({1}). Written to file ({2}).", imagePath, outputUid,
                        outputImagePath);
                }
            }
        }

        private static void ConfigureCodecPerSessionSettingsForOpenJpeg90()
        {
            string imagePath = "mr-knee.dcm";
            string outputImagePath = "mr-knee-openjpeg90-compressed.dcm";
            string outputUid = Uids.J2k90;

            OpjCodecOptions opjOptions = new OpjCodecOptions(outputUid) { J2kEncodeOverrides = "-p RLCP -r 30,10,5,1" };
            DicomSessionSettings sessionSettings = new DicomSessionSettings();
            sessionSettings.SetCodecOptions(opjOptions);

            using (DicomFileInput dfi = new DicomFileInput(imagePath))
            {
                DicomDataSet ds = dfi.ReadDataSet();
                using (DicomFileOutput dfo = new DicomFileOutput(outputImagePath, outputUid, sessionSettings))
                {
                    dfo.WriteDataSet(ds);
                    Console.WriteLine("Image ({0}) compressed successfully using ({1}). Written to file ({2}).", imagePath, outputUid,
                        outputImagePath);
                }
            }
        }
        private static void SaveConfigurationForJasper()
        {
            // Get the default jasper codec options for J2k91
            JasperCodecOptions jasperOptions = new JasperCodecOptions(Uids.J2k91);
            Logger.DebugFormat(DF.All, "Default jasper J2k91 options:{0}{1}", Environment.NewLine, jasperOptions);

            // Change the dll name to use the Jasper library with fractional bits=13
            jasperOptions.WinDllBaseName = "DCF_TSCWJasper13";
            jasperOptions.UnixDllBaseName = "DCF_TSCWJasper13";

            NameValueGroup overrides = DicomTSCodecOptions.CreateOverrides(jasperOptions);

            Logger.DebugFormat(DF.All, "Jasper overrides: {0}", overrides.GetDumper());

            // Write the serialized jasper NameValueGroup to disk
            NameValueWriter writer = new NameValueWriter();
            writer.WriteFile(JasperOverridesConfigFilename, overrides);
            Logger.DebugFormat(DF.All, "Jasper J2k91 overrides written to file({0})", JasperOverridesConfigFilename);
        }

        private static void ApplyOverridesForJasper()
        {
            // Load the default configuration, merging in the jasper codec overrides. This way, when the jasper codec options are
            // fetched, the overridden values are automatically applied.
            Framework.LoadConfiguration(JasperOverridesConfigFilename);
            JasperCodecOptions jasperOptions = new JasperCodecOptions(Uids.J2k91);
            Logger.DebugFormat(DF.All, "Jasper options after overrides applied:{0}{1}", Environment.NewLine, jasperOptions.ToString());
        }
        private static void ChangeJ2KCodecsToOpenJpeg()
        {
            // Load the default configuration, merging in the default session configuration overrides from a configuration file.
            // Demonstrate that the TSCodecFactory creates the Open JPEG codecs for the J2k supported transfer syntaxes.
            // Note that we can also put overrides for particular OpenJpeg options in this type of configuration.
            // Note that this configuration could also be read from a file or from the app config.
            string codecOptions = @"
# use JasperCodecOptions, OpjCodecOptions or AwareJ2kCodecOptions for 90
[ DCF.Dicom/default_session_cfg/CodecOptions/1.2.840.10008.1.2.4.90/Decode ]
_TYPE_ = LaurelBridge.DCF.Codecs.OpjCodecOptions
[ DCF.Dicom/default_session_cfg/CodecOptions/1.2.840.10008.1.2.4.90/Encode ]
_TYPE_ = LaurelBridge.DCF.Codecs.OpjCodecOptions
# Use progression order RLCP with 5 resolution levels
J2kEncodeOverrides = -p RLCP -r 20,10,5,2,1

# use JasperCodecOptions, OpjCodecOptions or AwareJ2kCodecOptions for 91
[ DCF.Dicom/default_session_cfg/CodecOptions/1.2.840.10008.1.2.4.91/Decode ]
_TYPE_ = LaurelBridge.DCF.Codecs.OpjCodecOptions
[ DCF.Dicom/default_session_cfg/CodecOptions/1.2.840.10008.1.2.4.91/Encode ]
_TYPE_ = LaurelBridge.DCF.Codecs.OpjCodecOptions
# Use 6 instead of the default 4 for the number of compression levels
J2kCompressionLevels = 6
";
            IDicomReader reader = new DicomStreamReader(Stream.Null);
            IDicomWriter writer = new DicomStreamWriter(Stream.Null);
            Framework.LoadConfiguration(new NameValueReader().ReadString(codecOptions));
            DicomTSCodecFactory codecFactory = DicomTSCodecFactory.Instance();
            foreach (string uid in new string[] { Uids.J2k90, Uids.J2k91 })
            {
                string uidName = DataDictionary.UidLookup.Find(uid).Name;
                DicomTSCodec rdrCodec = codecFactory.CreateTSCodec(uid, reader, null, null);
                DicomTSCodec wtrCodec = codecFactory.CreateTSCodec(uid, null, writer, null);
                if (rdrCodec is DicomTSCWCodec && wtrCodec is DicomTSCWCodec)
                {
                    DicomTSCWCodecOptions rdrOptions = (rdrCodec as DicomTSCWCodec).GetDicomTSCWCodecOptions();
                    DicomTSCWCodecOptions wtrOptions = (wtrCodec as DicomTSCWCodec).GetDicomTSCWCodecOptions();
                    Logger.InfoFormat("Reader CodecOptions({0}) for uid({1}) aka {2}: {3}", rdrOptions.GetType().Name,
                        uid, uidName, rdrOptions);
                    Logger.InfoFormat("Writer CodecOptions({0}) for uid({1}) aka {2}: {3}", wtrOptions.GetType().Name,
                        uid, uidName, wtrOptions);
                }
            }
        }
    }