# DecompressImageMultiframe.cs

    /*=========================================================================

      Program: GDCM (Grassroots DICOM). A DICOM library
      Module:  $URL$

      Copyright (c) 2006-2009 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;
        }
    }