/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2011 Mathieu Malaterre All rights reserved. See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /* $ gdcminfo ~/Desktop/angiogram-06.dcm MediaStorage is 1.2.840.10008.5.1.4.1.1.12.1 [X-Ray Angiographic Image Storage] TransferSyntax is 1.2.840.10008.1.2.4.50 [JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression] NumberOfDimensions: 3 Dimensions: (512,512,355) Origin: (0,0,0) Spacing: (1,1,40) DirectionCosines: (1,0,0,0,1,0) Rescale Intercept/Slope: (0,1) SamplesPerPixel :1 BitsAllocated :8 BitsStored :8 HighBit :7 PixelRepresentation:0 ScalarType found :UINT8 PhotometricInterpretation: MONOCHROME2 PlanarConfiguration: 0 TransferSyntax: 1.2.840.10008.1.2.4.50 Orientation Label: AXIAL */ /* * Description: * * Assume we have a file angiogram-06.dcm as described above. * the following program will decompress directly from the extracted jpeg stream. * * First step extract the jpeg stream (but not the Basic Offset Table): * * $ gdcmraw -i angiogram-06.dcm -o /tmp/output/chris --split-frags --pattern %d.jpg * * Check that indeed there are 355 files, while there are 356 fragments in the original DICOM file, since * gdcmraw always skip the first fragment (Basic Offset Table). * * Now from those individual jpeg stream, recreate a fake gdcm.DataElement... * * Usage: * * $ export LD_LIBRARY_PATH=$HOME/Projects/gdcm/debug-gcc/bin * $ mono ./bin/DecompressImageMultiframe.exe /tmp/output */ using System; using gdcm; public class DecompressImageMultiframe { public static int Main(string[] args) { string directory = args[0]; gdcm.Directory dir = new gdcm.Directory(); uint nfiles = dir.Load(directory); //System.Console.WriteLine(dir.toString()); gdcm.FilenamesType filenames = dir.GetFilenames(); Image image = new Image(); image.SetNumberOfDimensions( 3 ); // important for now DataElement pixeldata = new DataElement( new gdcm.Tag(0x7fe0,0x0010) ); // Create a new SequenceOfFragments C++ object, store it as a SmartPointer : SmartPtrFrag sq = SequenceOfFragments.New(); // Yeah, the file are not garantee to be in order, please adapt... for(uint i = 0; i < nfiles; ++i) { System.Console.WriteLine( filenames[(int)i] ); string file = filenames[(int)i]; System.IO.FileStream infile = new System.IO.FileStream(file, System.IO.FileMode.Open, System.IO.FileAccess.Read); uint fsize = gdcm.PosixEmulation.FileSize(file); byte[] jstream = new byte[fsize]; infile.Read(jstream, 0 , jstream.Length); Fragment frag = new Fragment(); frag.SetByteValue( jstream, new gdcm.VL( (uint)jstream.Length) ); sq.AddFragment( frag ); } // Pass by reference: pixeldata.SetValue( sq.__ref__() ); // insert: image.SetDataElement( pixeldata ); // JPEG use YBR to achieve better compression ratio by default (not RGB) // FIXME hardcoded: PhotometricInterpretation pi = new PhotometricInterpretation( PhotometricInterpretation.PIType.MONOCHROME2 ); image.SetPhotometricInterpretation( pi ); // FIXME hardcoded: PixelFormat pixeltype = new PixelFormat(1,8,8,7); image.SetPixelFormat( pixeltype ); // FIXME hardcoded: image.SetTransferSyntax( new TransferSyntax( TransferSyntax.TSType.JPEGLosslessProcess14_1 ) ); image.SetDimension(0, 512); image.SetDimension(1, 512); image.SetDimension(2, 355); // Decompress ! byte[] decompressedData = new byte[(int)image.GetBufferLength()]; image.GetBuffer(decompressedData); // Write out the decompressed bytes System.Console.WriteLine(image.toString()); using (System.IO.Stream stream = System.IO.File.Open(@"/tmp/dd.raw", System.IO.FileMode.Create)) { System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream); writer.Write(decompressedData); } return 0; } }