GDCM 2.2.0

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Directories
- Examples

Extracting_All_Resolution.cxx

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

      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.

    =========================================================================*/
    // This work was realised during the GSOC 2011 by Manoj Alwani

    #include <fstream>
    #include <openjpeg.h>
    #include <stdint.h>
    #include <string.h>
    #include <assert.h>
    #include <gdcm_j2k.h>
    #include <gdcm_jp2.h>
    #include<iostream>
    #include <cstring>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include "gdcmImageReader.h"
    #include "gdcmSequenceOfItems.h"
    #include "gdcmSystem.h"
    #include <fstream>

    #include "gdcmMediaStorage.h"
    #include "gdcmWriter.h"
    #include "gdcmItem.h"
    #include "gdcmImageReader.h"
    #include "gdcmAttribute.h"
    #include "gdcmFile.h"
    #include "gdcmTag.h"
    #include "gdcmTransferSyntax.h"
    #include "gdcmUIDGenerator.h"
    #include "gdcmAnonymizer.h"
    #include "gdcmStreamImageWriter.h"
    #include "gdcmImageHelper.h"
    #include "gdcmTrace.h"

    void error_callback(const char *msg, void *) {
      (void)msg;
    }
    void warning_callback(const char *msg, void *) {
      (void)msg;
    }
    void info_callback(const char *msg, void *) {
      (void)msg;
    }

    bool Write_Resolution(gdcm::StreamImageWriter & theStreamWriter, const char *filename, int res, std::ostream& of, int flag,  gdcm::SequenceOfItems *sq, int No_Of_Resolutions)
    {
      std::ifstream is;
      is.open( filename );
      opj_dparameters_t parameters;  /* decompression parameters */
      opj_event_mgr_t event_mgr;    /* event manager */
      opj_dinfo_t* dinfo;  /* handle to a decompressor */
      opj_cio_t *cio;
      opj_image_t *image = NULL;
      // FIXME: Do some stupid work:
      is.seekg( 0, std::ios::end);
      std::streampos buf_size = is.tellg();
      char *dummy_buffer = new char[(unsigned int)buf_size];
      is.seekg(0, std::ios::beg);
      is.read( dummy_buffer, buf_size);
      unsigned char *src = (unsigned char*)dummy_buffer;
      uint32_t file_length = (uint32_t)buf_size; // 32bits truncation should be ok since DICOM cannot have larger than 2Gb image

      /* configure the event callbacks (not required) */
      memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
      event_mgr.error_handler = error_callback;
      event_mgr.warning_handler = warning_callback;
      event_mgr.info_handler = info_callback;

      /* set decoding parameters to default values */
      opj_set_default_decoder_parameters(&parameters);

      // default blindly copied
      parameters.cp_layer=0;
      parameters.cp_reduce= res;
      //   parameters.decod_format=-1;
      //   parameters.cod_format=-1;

      const char jp2magic[] = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A";
      if( memcmp( src, jp2magic, sizeof(jp2magic) ) == 0 )
        {
        /* JPEG-2000 compressed image data ... sigh */
        // gdcmData/ELSCINT1_JP2vsJ2K.dcm
        // gdcmData/MAROTECH_CT_JP2Lossy.dcm
        //gdcmWarningMacro( "J2K start like JPEG-2000 compressed image data instead of codestream" );
        parameters.decod_format = 1; //JP2_CFMT;
        //assert(parameters.decod_format == JP2_CFMT);
        }
      else
        {
        /* JPEG-2000 codestream */
        //parameters.decod_format = J2K_CFMT;
        //assert(parameters.decod_format == J2K_CFMT);
        assert( 0 );
        }
      parameters.cod_format = 11; // PGX_DFMT;
      //assert(parameters.cod_format == PGX_DFMT);

      /* get a decoder handle */
        dinfo = opj_create_decompress(CODEC_JP2);

      /* catch events using our callbacks and give a local context */
      opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);

      /* setup the decoder decoding parameters using user parameters */
      opj_setup_decoder(dinfo, &parameters);

      /* open a byte stream */
      cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);

      /* decode the stream and fill the image structure */
      image = opj_decode(dinfo, cio);
      if(!image) {
        opj_destroy_decompress(dinfo);
        opj_cio_close(cio);
        //gdcmErrorMacro( "opj_decode failed" );
        return 1;
      }

           opj_cp_t * cp = ((opj_jp2_t*)dinfo->jp2_handle)->j2k->cp;
           opj_tcp_t *tcp = &cp->tcps[0];
           opj_tccp_t *tccp = &tcp->tccps[0];
        /*   std::cout << "\n No of Cols In Image" << image->x1;
           std::cout << "\n No of Rows In Image" << image->y1;
           std::cout << "\n No of Components in Image" << image->numcomps;
           std::cout << "\n No of Resolutions"<< tccp->numresolutions << "\n";
    */
            opj_j2k_t* j2k = NULL;
            opj_jp2_t* jp2 = NULL;
            jp2 = (opj_jp2_t*)dinfo->jp2_handle;
            int reversible = jp2->j2k->cp->tcps->tccps->qmfbid;
            //std:: cout << reversible;
           int compno = 0;
           opj_image_comp_t *comp = &image->comps[compno];
           int Dimensions[2];
           Dimensions[0]= comp->w;
           Dimensions[1] = comp->h;
           opj_cio_close(cio);
           unsigned long len = Dimensions[0]*Dimensions[1] * image->numcomps;
           //std::cout << "\nTest" <<image->comps[0].factor;
           char *raw = new char[len];
      for (unsigned int compno = 0; compno < (unsigned int)image->numcomps; compno++)
        {
        opj_image_comp_t *comp = &image->comps[compno];

        int w = image->comps[compno].w;
        int h = image->comps[compno].h;
          uint8_t *data8 = (uint8_t*)raw + compno;
          for (int i = 0; i < w * h ; i++)
            {
            int v = image->comps[compno].data[i];
            *data8 = (uint8_t)v;
            data8 += image->numcomps;
            }
        }

      gdcm::Writer w;
      gdcm::File &file = w.GetFile();
      gdcm::DataSet &ds = file.GetDataSet();

      file.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian );

      gdcm::UIDGenerator uid;
      gdcm::DataElement de( gdcm::Tag(0x8,0x18) ); // SOP Instance UID
      de.SetVR( gdcm::VR::UI );
      const char *u = uid.Generate();
      de.SetByteValue( u, strlen(u) );
      ds.Insert( de );

      gdcm::DataElement de1( gdcm::Tag(0x8,0x16) );
      de1.SetVR( gdcm::VR::UI );
      gdcm::MediaStorage ms( gdcm::MediaStorage::CTImageStorage );
      de1.SetByteValue( ms.GetString(), strlen(ms.GetString()));
      ds.Insert( de1 );

      const char mystr[] = "MONOCHROME2 ";
      gdcm::DataElement de2( gdcm::Tag(0x28,0x04) );
      //de.SetTag(gdcm::Tag(0x28,0x04));
      de2.SetVR( gdcm::VR::CS );
      de2.SetByteValue(mystr, strlen(mystr));
      ds.Insert( de2 );

       gdcm::Attribute<0x0028,0x0010> row = {image->comps[0].w};
       //row.SetValue(512);
       ds.Insert( row.GetAsDataElement() );
     //  w.SetCheckFileMetaInformation( true );
       gdcm::Attribute<0x0028,0x0011> col = {image->comps[0].h};
       ds.Insert( col.GetAsDataElement() );
       gdcm::Attribute<0x0028,0x0008> Number_Of_Frames = {1};
       ds.Insert( Number_Of_Frames.GetAsDataElement() );

       gdcm::Attribute<0x0028,0x0100> at = {8};
       ds.Insert( at.GetAsDataElement() );

       gdcm::Attribute<0x0028,0x0002> at1 = {image->numcomps};
       ds.Insert( at1.GetAsDataElement() );

      gdcm::Attribute<0x0028,0x0101> at2 = {8};
       ds.Insert( at2.GetAsDataElement() );

      gdcm::Attribute<0x0028,0x0102> at3 = {7};
      ds.Insert( at3.GetAsDataElement() );

      if (flag == 1)
      {

        for (int i=0; i < No_Of_Resolutions; i++)
        {

         int a = 1;
         int b =1;

         while(a!=((No_Of_Resolutions)-i))
            {
              b = b*2;
              a = a+1;
             }
         uint16_t row = (image->y1)/b;
         uint16_t col = (image->x1)/b;
         //std::cout << row;
         gdcm::Element<gdcm::VR::IS,gdcm::VM::VM1> el2;
         el2.SetValue(i+1);
         gdcm::DataElement rfn = el2.GetAsDataElement();     //ulr --> upper left row
         rfn.SetTag( gdcm::Tag(0x0008,0x1160) );

         gdcm::Element<gdcm::VR::US,gdcm::VM::VM2> el;
         el.SetValue(1,0);
         el.SetValue(1,1);
         gdcm::DataElement ulr = el.GetAsDataElement();     //ulr --> upper left col/row
         ulr.SetTag( gdcm::Tag(0x0048,0x0201) );

         gdcm::Element<gdcm::VR::US,gdcm::VM::VM2> el1;
         el1.SetValue(col,0);
         el1.SetValue(row,1);
         gdcm::DataElement brr = el1.GetAsDataElement();
         brr.SetTag( gdcm::Tag(0x0048,0x0202) );            //brr --> bottom right col/row
        gdcm::Item it;
        gdcm::DataSet &nds = it.GetNestedDataSet();
        nds.Insert( rfn );
        nds.Insert(ulr);
        nds.Insert(brr);

        sq->AddItem(it);
      }

      gdcm::Writer w1;
      gdcm::File &file1 = w1.GetFile();
      gdcm::DataSet &ds1 = file1.GetDataSet();
      file1.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian );

      gdcm::UIDGenerator uid1;
      gdcm::DataElement dea( gdcm::Tag(0x8,0x18) ); // SOP Instance UID
      dea.SetVR( gdcm::VR::UI );
      const char *u1 = uid1.Generate();
      dea.SetByteValue( u1, strlen(u1) );
      ds1.Insert( dea );

      gdcm::DataElement deb( gdcm::Tag(0x8,0x16) );
      deb.SetVR( gdcm::VR::UI );
      gdcm::MediaStorage ms1( gdcm::MediaStorage::VLWholeSlideMicroscopyImageStorage );
      deb.SetByteValue( ms1.GetString(), strlen(ms1.GetString()));
      ds1.Insert( deb );

      const char mystr1[] = "MONOCHROME2 ";
      gdcm::DataElement dec( gdcm::Tag(0x28,0x04) );
      //de.SetTag(gdcm::Tag(0x28,0x04));
      dec.SetVR( gdcm::VR::CS );
      dec.SetByteValue(mystr, strlen(mystr1));
      ds1.Insert( dec );

       gdcm::Attribute<0x0028,0x0010> row1 = {image->y1};
       //row.SetValue(512);
       ds1.Insert( row1.GetAsDataElement() );
     //  w.SetCheckFileMetaInformation( true );
       gdcm::Attribute<0x0028,0x0011> col1 = {image->x1};
       ds1.Insert( col1.GetAsDataElement() );
       gdcm::Attribute<0x0028,0x0008> Number_Of_Frames1 = {tccp->numresolutions};
       ds1.Insert( Number_Of_Frames1.GetAsDataElement() );

       gdcm::Attribute<0x0028,0x0100> ata = {8};
       ds1.Insert( ata.GetAsDataElement() );

       gdcm::Attribute<0x0028,0x0002> atb = {image->numcomps};
       ds1.Insert( atb.GetAsDataElement() );

      gdcm::Attribute<0x0028,0x0101> atc = {8};
       ds1.Insert( atc.GetAsDataElement() );

      gdcm::Attribute<0x0028,0x0102> atd = {7};
      ds1.Insert( atd.GetAsDataElement() );

       theStreamWriter.SetFile(file1);

      gdcm::DataElement des( gdcm::Tag(0x0048,0x0200) );
      des.SetVR(gdcm::VR::SQ);
      //des.SetVR(gdcm::VM::VM1);
      des.SetValue(*sq);
      des.SetVLToUndefined();

      ds1.Insert(des);

      if (!theStreamWriter.WriteImageInformation()){
          std::cerr << "unable to write image information" << std::endl;
          return 1; //the CanWrite function should prevent getting here, else,
          //that's a test failure
        }

     }

       theStreamWriter.SetFile(file);

      if (!theStreamWriter.CanWriteFile()){
          delete [] raw;
          std::cout << "Not able to write";
          return 0;//this means that the file was unwritable, period.
          //very similar to a ReadImageInformation failure
        }
    else
       std::cout<<"\nabletoread";

     // Important to write here
     std::vector<unsigned int> extent = gdcm::ImageHelper::GetDimensionsValue(file);

        unsigned short xmax = extent[0];
        unsigned short ymax = extent[1];
        unsigned short theChunkSize = 4;
        unsigned short ychunk = extent[1]/theChunkSize; //go in chunk sizes of theChunkSize
        unsigned short zmax = extent[2];
        std::cout << "\n"<<xmax << "\n" << ymax<<"\n"<<zmax<<"\n" << image->numcomps<<"\n";

        if (xmax == 0 || ymax == 0)
          {
          std::cerr << "Image has no size, unable to write zero-sized image." << std::endl;
          return 0;
          }

        int z, y, nexty;
        unsigned long prevLen = 0; //when going through the char buffer, make sure to grab
        //the bytes sequentially.  So, store how far you got in the buffer with each iteration.
        for (z = 0; z < zmax; ++z){
          for (y = 0; y < ymax; y += ychunk){
            nexty = y + ychunk;
            if (nexty > ymax) nexty = ymax;
            theStreamWriter.DefinePixelExtent(0, xmax, y, nexty, z, z+1);
            unsigned long len = theStreamWriter.DefineProperBufferLength();
            std::cout << "\n" <<len;
            char* finalBuffer = new char[len];
            memcpy(finalBuffer, &(raw[prevLen]), len);
            std::cout << "\nable to write";
            if (!theStreamWriter.Write(finalBuffer, len)){
              std::cerr << "writing failure:" << "output.dcm" << " at y = " << y << " and z= " << z << std::endl;
              delete [] raw;
              delete [] finalBuffer;
              return 1;
            }
            delete [] finalBuffer;
            prevLen += len;
          }
        }
        delete raw;

      delete[] src;  //FIXME

    if(dinfo) {
        opj_destroy_decompress(dinfo);
      }

     opj_image_destroy(image);

     return true;

    }

    bool Different_Resolution( gdcm::StreamImageWriter & theStreamWriter, const char *filename, int res, std::ostream& of)
    {
      //std::vector<std::string>::const_iterator it = filenames.begin();
      bool b = true;
      int flag = 1;

     gdcm::SmartPointer<gdcm::SequenceOfItems> sq = new gdcm::SequenceOfItems();
     sq->SetLengthToUndefined();

      for(int i = res-1 ; i>=0; --i)
      {
        b = b && Write_Resolution( theStreamWriter, filename, i, of ,flag,sq,res);
       // b = b && Get_Resolution( theStreamWriter, filename, i, of ,0);
        flag = 0;
      }
      //b = b && Get_Lowest_Resolution( writer, sq, filename, res-1 );
      //b = b && PopulateSingeFile( writer, sq, jpeg, filename2 );
      //image.SetDimension(2,  res )
      return b;
    }

    int main(int argc, char *argv[])
    {

       if( argc < 4 )
        {
        std::cerr << argv[0] << " input.jp2 output.dcm No. Of Resolutions " << std::endl;
        return 1;
        }
       const char *filename = argv[1];
      const char *outfilename = argv[2];
      char *resolutions = argv[3];
       int res = int((*resolutions)-48);
        //std:: cout << "\nres"<< res;
       gdcm::StreamImageWriter theStreamWriter;

       std::ofstream of;
       of.open( outfilename, std::ios::out | std::ios::binary );
       theStreamWriter.SetStream(of);

       if( !Different_Resolution( theStreamWriter, filename,res,of ) ) return 1;

     uint16_t firstTag1 =  0xfffe;
     uint16_t secondTag1 = 0xe0dd;
     uint32_t thirdTag1 =  0x00000000;
     //uint16_t fourthTag1 = 0xffff;
     const int theBufferSize1 = 2*sizeof(uint16_t)+sizeof(uint32_t);
     char* tmpBuffer2 = new char[theBufferSize1];
     memcpy(&(tmpBuffer2[0]), &firstTag1, sizeof(uint16_t));
     memcpy(&(tmpBuffer2[sizeof(uint16_t)]), &secondTag1, sizeof(uint16_t));
     memcpy(&(tmpBuffer2[2*sizeof(uint16_t)]), &thirdTag1, sizeof(uint32_t));
     //memcpy(&(tmpBuffer2[3*sizeof(uint16_t)]), &fourthTag1, sizeof(uint16_t));
     assert( of && !of.eof() && of.good() );
     of.write(tmpBuffer2, theBufferSize1);
     of.flush();
     assert( of );

    return 0;
    }