tinydicom + rawprocessor lesson #2

      Comments Off on tinydicom + rawprocessor lesson #2

Now it’s time to next step for using my open sources,  And here I like to introduce how loads DCM and what it contains inside tags.

Just read my example code to read DICOM tags from DCM file, it should help what inside.

#ifdef __APPLE__
    #include <sys/uio.h>
#elif _WIN32
    #include <io.h>
#else
    #include <sys/io.h>
#endif

#include <cstdio>
#include <cstdlib>

// -- std ---
#include <string>
#include <vector>

using namespace std;

// -- other headers --
#include "libdcm.h"

////////////////////////////////////////////////////////////////////////////////

#define MADE_DATE               "2017-04-18-0"

////////////////////////////////////////////////////////////////////////////////

const char sampledcm[] = "SIMFIT.dcm";

////////////////////////////////////////////////////////////////////////////////

void testDCM()
{
    printf( "#TEST: Loading DCM #\n" );
    printf( "Loading DCM file : %s ... ", sampledcm );

    if ( OpenDCM( sampledcm ) == true )
    {
        printf( "Ok.\n" );

        printf( "Check elements : " );
        int elemsz = GetElementCount();
        printf( "%d elements found.\n", elemsz );

        if ( elemsz > 0 )
        {
            for( int cnt=0; cnt<elemsz; cnt++ )
            {
                DCMTagElement* elem = NULL;
                if ( GetElement( cnt, &elem ) > 0  )
                {
                    printf( "\t[%03d : %c%c] ID = %04X:%04X , size = %d bytes \n",
                            cnt + 1,
                            elem->VRtype[0],
                            elem->VRtype[1],
                            ( elem->id & 0xFFFF0000 ) >> 16,
                            elem->id & 0x0000FFFF,
                            elem->size );

                    delete elem;
                }
            }
        }

        CloseDCM();
    }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

int main( int argc, char** argv )
{
    printf( "librawprocessor + libtinydicom, examples : %s\n", MADE_DATE);
    printf( "(C)2017, Raph.K.\n");

    testDCM();
 
    return 0;
}

It may compiles with libtinydicom.a linkage as well, just compile your code with -ltinydicom -L{libtinydicom.a directory from your path}. Or, just follow my way – Make an empty directory in your working directory –  I like to recommend to make a directory as like ‘projects’. Then make a new again for unique name to check for next time, or continue to more works : recommend ‘dcmtest1’ or ‘dcmtest2’. So you may now placed to {Your home directory}/projects/dcmtest1 when you had followed my recommendation. Now make a empty cpp file with any editor like vim, then copy & paste my example, then save it up and quit editor. Then copy prebuilt “libtinydicom.a” and “libdcm.h” into your current directory – if you didn’t prebuilt? just build it first. and type like this.

g++ main.cpp -ltinydicom -o test1

You may check test1 or test1.exe (on Windows).
Now you need download sample DCM file from here:

http://tomintechsupport.com/dicom/smpte_simfit/

If you have wget, you can do :

wget http://tomintechsupport.com/download/SIMFIT.dcm

Now you have SIMFIT.dcm and compiled binary with same directory. Just type your binary name. And check result. 87 items may displayed with sizes.

 

Then, try to next step, save raw pixel image to a new file. See my example source.

#ifdef __APPLE__
    #include <sys/uio.h>
#elif _WIN32
    #include <io.h>
#else
    #include <sys/io.h>
#endif

#include <cstdio>
#include <cstdlib>

// -- std ---
#include <string>
#include <vector>

using namespace std;

// -- other headers --
#include "rawprocessor.h"
#include "libdcm.h"

////////////////////////////////////////////////////////////////////////////////

#define MADE_DATE               "2017-04-18-0"

////////////////////////////////////////////////////////////////////////////////

const char sampledcm[] = "SIMFIT.dcm";

////////////////////////////////////////////////////////////////////////////////

void testDCM2RAW()
{
    printf( "#TEST: DCM to RAW image#\n" );
    printf( "Loading DCM file : %s ... ", sampledcm );

    if ( OpenDCM( sampledcm ) == true )
    {
        printf( "Ok.\n" );

        printf( "Check pixel data elements : " );

        ImageInformation iinfo = {0};

        if ( ReadPixelData( &iinfo ) == true )
        {
            printf( "Ok.\n" );

            // Convert DCM raw image info to RAW image processor.

            RAWProcessor* rawproc = new RAWProcessor();

            if ( rawproc != NULL )
            {
                int datasz = 2;

                if ( iinfo.bpp <= 8 )
                {
                    datasz = 1;
                }

                printf( "Converting to RAW image ... " );
                bool retb = \
                rawproc->LoadFromMemory( (const char*)iinfo.pixels,
                                         iinfo.width * iinfo.height * datasz,
                                         0, /// No transform
                                         iinfo.height );
                if ( retb == true )
                {
                    // Make RAW image to simply dumped as a file.
                    char tmpstr[128] = {0};

                    sprintf( tmpstr, "rawdump_w%d_h%d.raw", iinfo.width, iinfo.height );

                    if ( rawproc->SaveToFile( tmpstr ) == true )
                    {
                        printf( "Ok, dumped a file : %s\n", tmpstr );

                        printf( "raw image sizes : %d x %d\n", rawproc->Width(), rawproc->Height() );
                    }
                    else
                    {
                        printf( "Failed to dump a file.\n" );
                    }

                    printf( "Finding window center and width ... " );
                    // And then, process a little.
                    // Find DICOM window center and width.

                    DCMTagElement* dcmtag = NULL;

                    unsigned w_center = 0;
                    unsigned w_width  = 0;
                    int      l_min    = 0;
                    int      l_max    = 0;

                    dcmtag = FindElement( 0x00281050 ); /// window center
                    if ( dcmtag != NULL )
                    {
                        w_center = atoi( dcmtag->staticbuffer );
                    }

                    dcmtag = FindElement( 0x00281051 ); /// window width
                    if ( dcmtag != NULL )
                    {
                        unsigned w_width = atoi( dcmtag->staticbuffer );
                        if ( ( w_width > 0 ) && ( w_center == 0 ) )
                        {
                            w_center = w_width / 2;
                        }

                        l_max = w_center + w_width / 2;
                        l_min = w_center - w_width / 2;

                        if ( l_min < 0 )
                        {
                            l_min = 0;
                        }
                    }

                    if ( l_min < l_max )
                    {
                        printf( "Ok,\nProcessing to thresholded image ... " );

                        // Make thresholded image.
                        RAWProcessor::WeightAnalysisReport wreport = {0};
                        rawproc->GetAnalysisReport( wreport );
                        wreport.threshold_wide_min = l_min;
                        wreport.threshold_wide_max = l_max;

                        vector< unsigned short > thresholded;

                        if ( rawproc->Get16bitThresholdedImage( wreport, &thresholded ) == true )
                        {
                            RAWProcessor* rawproc_th = new RAWProcessor();
                            if ( rawproc_th != NULL )
                            {
                                bool retb = \
                                rawproc_th->LoadFromMemory( (const char*) thresholded.data(),
                                                            thresholded.size() * sizeof( unsigned short ),
                                                            0,
                                                            rawproc->Height() );

                                if ( retb == true )
                                {
                                    printf( "Ok.\n" );

                                    sprintf( tmpstr,
                                             "rawposteffected_w%d_h%d.raw",
                                             rawproc_th->Width(),
                                             rawproc_th->Height() );

                                    rawproc_th->SaveToFile( tmpstr );
                                }
                                else
                                {
                                    printf( "Failed to load image from memory.\n" );
                                }

                                delete rawproc_th;
                            }
                        }
                        else
                        {
                            printf( "Failed to get thresholded image.\n" );
                        }
                    }

                    delete rawproc;
                }
                else
                {
                    printf( "Failure.\n ");
                }

            }
        }
        else
        {
            printf( "Failure.\n" );
        }

        CloseDCM();
    }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

int main( int argc, char** argv )
{
    printf( "librawprocessor + libtinydicom, examples : %s\n", MADE_DATE);
    printf( "(C)2017, Raph.K.\n");

    testDCM2RAW();

    return 0;
}

Now you need prebuilt librawprocessor.a and rawprocessor.h file in your directory with example source code. It proceeds read SIMFIT.DCM and export pixel image information, then writes to a file.

Important points is ‘Checking Window center and width’ from DICOM tag ID 0028:1050 and 0028:1051. These tags contains information of window center and width, and it must applied to exported image. So I used Get16bitThresholdedImage() method to make windowed image.

If you need more detailed? just let left a guestbook here.

Next lesson may using libPNG, and make raw image to 8bit grey scaled image to see in common image viewing programs.