Read a few tags - DICOM

This is a discussion on Read a few tags - DICOM ; I have been given a series of DICOM files and want to extract the values of a few tags and the image intensity values for some data processing. E.g. 0020,1041,Slice Location 0018,1310,Acquisition Matrix 0018,0081,Echo Time I have looked at the ...

+ Reply to Thread
Results 1 to 15 of 15

Thread: Read a few tags

  1. Read a few tags

    I have been given a series of DICOM files and want to extract the
    values of a few tags and the image intensity values for some data
    processing. E.g.

    0020,1041,Slice Location
    0018,1310,Acquisition Matrix
    0018,0081,Echo Time

    I have looked at the source code of a few packages on the web but am
    struggling with the sheer volume of "stuff" to wade through, due to
    DICOM having to be so general. I'm wondering if there's a simple way
    just to pull out the tags I need without using a general package? I am
    hoping for something along the lines of...

    fopen( filename )
    fseek( tag_index )
    fread( value )
    fclose()

    Please excuse the pseudo code

  2. Re: Read a few tags

    On May 14, 2:33 am, spasmous2 wrote:
    > I have been given a series of DICOM files and want to extract the
    > values of a few tags and the image intensity values for some data
    > processing. E.g.
    >
    > 0020,1041,Slice Location
    > 0018,1310,Acquisition Matrix
    > 0018,0081,Echo Time
    >
    > I have looked at the source code of a few packages on the web but am
    > struggling with the sheer volume of "stuff" to wade through, due to
    > DICOM having to be so general. I'm wondering if there's a simple way
    > just to pull out the tags I need without using a general package? I am
    > hoping for something along the lines of...
    >
    > fopen( filename )
    > fseek( tag_index )
    > fread( value )
    > fclose()
    >
    > Please excuse the pseudo code


    If you are dealing with a single source producing the DICOM file, then
    yes you can hack your way to write something 'not general'. You need
    to know the endianess, and whether or not your file are implicit or
    explicit. Then get PS 3.5 & PS 3.6 from the dicom standard. PS 3.5
    will explain how to read the file (technically you should be getting
    PS 3.10 compliant file), and PS 3.6 will tell you the encoding for
    each tag.


    Use GDCM / dcmtk / dicom3tools and your favorite scripting language
    instead of trying to write code meant to be thrown away.

    eg:
    $ gdcmdump myfile.dcm | grep "Name of My Tag"


    -Mathieu

  3. Re: Read a few tags

    On May 13, 10:57*pm, Mathieu Malaterre
    wrote:
    > On May 14, 2:33 am, spasmous2 wrote:
    >
    >
    >
    > > I have been given a series of DICOM files and want to extract the
    > > values of a few tags and the image intensity values for some data
    > > processing. E.g.

    >
    > > 0020,1041,Slice Location
    > > 0018,1310,Acquisition Matrix
    > > 0018,0081,Echo Time

    >
    > > I have looked at the source code of a few packages on the web but am
    > > struggling with the sheer volume of "stuff" to wade through, due to
    > > DICOM having to be so general. I'm wondering if there's a simple way
    > > just to pull out the tags I need without using a general package? I am
    > > hoping for something along the lines of...

    >
    > > fopen( filename )
    > > fseek( tag_index )
    > > fread( value )
    > > fclose()

    >
    > > Please excuse the pseudo code

    >
    > If you are dealing with a single source producing the DICOM file, then
    > yes you can hack your way to write something 'not general'. You need
    > to know the endianess, and whether or not your file are implicit or
    > explicit. Then get PS 3.5 & PS 3.6 from the dicom standard. PS 3.5
    > will explain how to read the file (technically you should be getting
    > PS 3.10 compliant file), and PS 3.6 will tell you the encoding for
    > each tag.
    >


    Thanks for your reply. I am looking at the documentation now. Sorry if
    this is a really dumb question but how do I interpret the numbers
    (0018,0081)? From what I learnt, in DICOM there are 128 bytes of
    leading zeros then the letters DICM. After that I can't quite see how
    to translate (0018,0081) into an index where the value is stored - any
    clue?

  4. Re: Read a few tags

    On May 14, 6:40 pm, spasmous2 wrote:
    > On May 13, 10:57 pm, Mathieu Malaterre
    > wrote:
    >
    >
    >
    > > On May 14, 2:33 am, spasmous2 wrote:

    >
    > > > I have been given a series of DICOM files and want to extract the
    > > > values of a few tags and the image intensity values for some data
    > > > processing. E.g.

    >
    > > > 0020,1041,Slice Location
    > > > 0018,1310,Acquisition Matrix
    > > > 0018,0081,Echo Time

    >
    > > > I have looked at the source code of a few packages on the web but am
    > > > struggling with the sheer volume of "stuff" to wade through, due to
    > > > DICOM having to be so general. I'm wondering if there's a simple way
    > > > just to pull out the tags I need without using a general package? I am
    > > > hoping for something along the lines of...

    >
    > > > fopen( filename )
    > > > fseek( tag_index )
    > > > fread( value )
    > > > fclose()

    >
    > > > Please excuse the pseudo code

    >
    > > If you are dealing with a single source producing the DICOM file, then
    > > yes you can hack your way to write something 'not general'. You need
    > > to know the endianess, and whether or not your file are implicit or
    > > explicit. Then get PS 3.5 & PS 3.6 from the dicom standard. PS 3.5
    > > will explain how to read the file (technically you should be getting
    > > PS 3.10 compliant file), and PS 3.6 will tell you the encoding for
    > > each tag.

    >
    > Thanks for your reply. I am looking at the documentation now. Sorry if
    > this is a really dumb question but how do I interpret the numbers
    > (0018,0081)? From what I learnt, in DICOM there are 128 bytes of
    > leading zeros then the letters DICM. After that I can't quite see how
    > to translate (0018,0081) into an index where the value is stored - any
    > clue?


    They'll written in hexadecimal (see PS 3.5). So with your favorite
    hexeditor look for '0x0012' next to '0x0051'.

    On a personal note, you would be done by now using an existing DICOM
    library...

    -Mathieu

  5. Re: Read a few tags

    On May 14, 5:33 am, spasmous2 wrote:
    > I have been given a series of DICOM files and want to extract the
    > values of a few tags and the image intensity values for some data
    > processing. E.g.
    >
    > 0020,1041,Slice Location
    > 0018,1310,Acquisition Matrix
    > 0018,0081,Echo Time
    >
    > I have looked at the source code of a few packages on the web but am
    > struggling with the sheer volume of "stuff" to wade through, due to
    > DICOM having to be so general. I'm wondering if there's a simple way
    > just to pull out the tags I need without using a general package? I am
    > hoping for something along the lines of...
    >
    > fopen( filename )
    > fseek( tag_index )
    > fread( value )
    > fclose()
    >
    > Please excuse the pseudo code


    Hi,
    have you tried the MyDICOM.NET SDK Package.
    The expected functionality using that SDK is quite simple.
    Try that...

  6. Re: Read a few tags

    On May 15, 1:08*am, Mathieu Malaterre
    wrote:
    > On May 14, 6:40 pm, spasmous2 wrote:
    >
    >
    >
    > > On May 13, 10:57 pm, Mathieu Malaterre
    > > wrote:

    >
    > > > On May 14, 2:33 am, spasmous2 wrote:

    >
    > > > > I have been given a series of DICOM files and want to extract the
    > > > > values of a few tags and the image intensity values for some data
    > > > > processing. E.g.

    >
    > > > > 0020,1041,Slice Location
    > > > > 0018,1310,Acquisition Matrix
    > > > > 0018,0081,Echo Time

    >
    > > > > I have looked at the source code of a few packages on the web but am
    > > > > struggling with the sheer volume of "stuff" to wade through, due to
    > > > > DICOM having to be so general. I'm wondering if there's a simple way
    > > > > just to pull out the tags I need without using a general package? I am
    > > > > hoping for something along the lines of...

    >
    > > > > fopen( filename )
    > > > > fseek( tag_index )
    > > > > fread( value )
    > > > > fclose()

    >
    > > > > Please excuse the pseudo code

    >
    > > > If you are dealing with a single source producing the DICOM file, then
    > > > yes you can hack your way to write something 'not general'. You need
    > > > to know the endianess, and whether or not your file are implicit or
    > > > explicit. Then get PS 3.5 & PS 3.6 from the dicom standard. PS 3.5
    > > > will explain how to read the file (technically you should be getting
    > > > PS 3.10 compliant file), and PS 3.6 will tell you the encoding for
    > > > each tag.

    >
    > > Thanks for your reply. I am looking at the documentation now. Sorry if
    > > this is a really dumb question but how do I interpret the numbers
    > > (0018,0081)? From what I learnt, in DICOM there are 128 bytes of
    > > leading zeros then the letters DICM. After that I can't quite see how
    > > to translate (0018,0081) into an index where the value is stored - any
    > > clue?

    >
    > They'll written in hexadecimal (see PS 3.5). So with your favorite
    > hexeditor look for '0x0012' next to '0x0051'.
    >
    > On a personal note, you would be done by now using an existing DICOM
    > library...
    >


    Heh if life were so simple... I have your GDCM package on my computer.
    Except it wants to use Cmake which I don't have, so I downloaded that
    too. Now I find the error : Bad Interpreter : No such file or
    directory. And this is before I even try compiling! Got to laugh...

    Looking through the dicom header with a hex editor I don't see the
    tags I want either. lol... cry... lol!

  7. Re: Read a few tags

    On May 15, 6:59 pm, spasmous2 wrote:
    > On May 15, 1:08 am, Mathieu Malaterre
    > wrote:
    >
    >
    >
    > > On May 14, 6:40 pm, spasmous2 wrote:

    >
    > > > On May 13, 10:57 pm, Mathieu Malaterre
    > > > wrote:

    >
    > > > > On May 14, 2:33 am, spasmous2 wrote:

    >
    > > > > > I have been given a series of DICOM files and want to extract the
    > > > > > values of a few tags and the image intensity values for some data
    > > > > > processing. E.g.

    >
    > > > > > 0020,1041,Slice Location
    > > > > > 0018,1310,Acquisition Matrix
    > > > > > 0018,0081,Echo Time

    >
    > > > > > I have looked at the source code of a few packages on the web but am
    > > > > > struggling with the sheer volume of "stuff" to wade through, due to
    > > > > > DICOM having to be so general. I'm wondering if there's a simple way
    > > > > > just to pull out the tags I need without using a general package? I am
    > > > > > hoping for something along the lines of...

    >
    > > > > > fopen( filename )
    > > > > > fseek( tag_index )
    > > > > > fread( value )
    > > > > > fclose()

    >
    > > > > > Please excuse the pseudo code

    >
    > > > > If you are dealing with a single source producing the DICOM file, then
    > > > > yes you can hack your way to write something 'not general'. You need
    > > > > to know the endianess, and whether or not your file are implicit or
    > > > > explicit. Then get PS 3.5 & PS 3.6 from the dicom standard. PS 3.5
    > > > > will explain how to read the file (technically you should be getting
    > > > > PS 3.10 compliant file), and PS 3.6 will tell you the encoding for
    > > > > each tag.

    >
    > > > Thanks for your reply. I am looking at the documentation now. Sorry if
    > > > this is a really dumb question but how do I interpret the numbers
    > > > (0018,0081)? From what I learnt, in DICOM there are 128 bytes of
    > > > leading zeros then the letters DICM. After that I can't quite see how
    > > > to translate (0018,0081) into an index where the value is stored - any
    > > > clue?

    >
    > > They'll written in hexadecimal (see PS 3.5). So with your favorite
    > > hexeditor look for '0x0012' next to '0x0051'.

    >
    > > On a personal note, you would be done by now using an existing DICOM
    > > library...

    >
    > Heh if life were so simple... I have your GDCM package on my computer.
    > Except it wants to use Cmake which I don't have, so I downloaded that
    > too. Now I find the error : Bad Interpreter : No such file or
    > directory. And this is before I even try compiling! Got to laugh...


    I have never seen this error before: but I do not know your OS, I do
    not know your compiler, I do not know what you did. anyway if this is
    an issue with cmake I'd suggest the cmake mailing list:

    http://www.cmake.org/mailman/listinfo/cmake

    If this is an issue with GDCM:

    https://lists.sourceforge.net/lists/...dcm-developers

    > Looking through the dicom header with a hex editor I don't see the
    > tags I want either. lol... cry... lol!


    If you can send me -privately- a copy of one of your file.

    Thanks
    -Mathieu

  8. Re: Read a few tags

    Hello spasmous2,

    Having read the discussion up to now, I think I have to drop in a line
    or two about the field you would like to plow. I do not want to
    discourage you, but instead create an idea of the size of map you want
    to draw.

    I am afraid that you face a tough job if you want to do it *without*
    using one of the recommended libraries (you received links to quite a
    few, and in this group, others are regularly announced and discussed,
    use groups.google.com to find out yourself).

    spasmous2 wrote:
    >
    > I am looking at the documentation now. Sorry if
    > this is a really dumb question but how do I interpret the numbers
    > (0018,0081)? From what I learnt, in DICOM there are 128 bytes of
    > leading zeros then the letters DICM. After that I can't quite see how
    > to translate (0018,0081) into an index where the value is stored - any
    > clue?


    Well, basically, you have a binary structure of the file preamble, and
    then there is a tagged file format with 4 Byte of "Tag" (e. g.
    0x008,0x005), then
    * in Explicit Transfer Syntaxes a Value representation with
    two Byte of length for Value Representations that may hold "small"
    content, or
    two zero Byte padding and
    four Bytes of Content Length for Value Representations holding long
    content

    * In Implicit Transfer Syntaxes, the Tag is always followed by 4 Byte of
    length.

    There are Little Endian Syntaxes as well as Big Endian Syntaxes. There
    may be deflated Syntax.

    Some Tags may hold sequences (a "mini-Dataset" of other Tags) with
    several Items. These may have undefined length, so you will only stay in
    sync when parsing "everything".

    Can you see it is not that easy? This *is* complicated.

    To get a basic understanding, please read part 5 of the DICOM Standard
    thoroughly. Then read related parts (in some way, all are related). It
    is hard to get started, I agree, but an "easy way" will not do the job
    you described safely and an conformant way.

    I do not want to discourage you, but the ambition to implement "DICOM
    quickly" is high.

    If you really need only "some attribute's content", use a lib. Or even
    more simplified, spawn a console dump tool available in many different
    flavors from many different toolkits in many different license models
    and parse their output.

    Personally, I would recommend to use a DICOM to XML dump tool (which
    typically do not include binary payload data like pixel data or digital
    waveforms in their output) and parse the output XML tree until you got
    your information, this is safe and still rather easy. The tool to recall
    right from the top of my head would be dcmtk's dicom2xml (->
    http://dicom.offis.de/dcmtk.php.en), but I am sure there are many others.

    Then, if you want to find out basic information about the Attributes you
    have now parsed _correctly_ (the toolkit does the trick) without having
    to implement Part 5 yourselves, you may take the shortcut of looking up
    the Tag in Part 6 and the Semantics in Part 3, and you are almost done ;-)

    If you want to start digging deeply into the DICOM world, of course, you
    may want to implement everything from the scratch. Start a parser for
    DICOM Data sets, then add Sequence Support and so on. This is not a
    holiday game, it will take time, nerve and motivation, but within some
    few years, you will maybe able to provide a toolkit yourselves.

    I hope this helps, it's just my EUR 0.02


    Have a nice weekend,


    Peter

  9. Re: Read a few tags

    On May 17, 5:51*am, Peter B Schmidt wrote:
    > Hello spasmous2,
    >
    > Having read the discussion up to now, I think I have to drop in a line
    > or two about the field you would like to plow. I do not want to
    > discourage you, but instead create an idea of the size of map you want
    > to draw.
    >
    > I am afraid that you face a tough job if you want to do it *without*
    > using one of the recommended libraries (you received links to quite a
    > few, and in this group, others are regularly announced and discussed,
    > use groups.google.com to find out yourself).
    >
    > spasmous2 wrote:
    >
    > > I am looking at the documentation now. Sorry if
    > > this is a really dumb question but how do I interpret the numbers
    > > (0018,0081)? From what I learnt, in DICOM there are 128 bytes of
    > > leading zeros then the letters DICM. After that I can't quite see how
    > > to translate (0018,0081) into an index where the value is stored - any
    > > clue?

    >
    > Well, basically, you have a binary structure of the file preamble, and
    > then there is a tagged file format with 4 Byte of "Tag" (e. g.
    > 0x008,0x005), then
    > * in Explicit Transfer Syntaxes a Value representation with
    > * * two Byte of length for Value Representations that may hold "small"
    > content, or
    > * * two zero Byte padding and
    > * * four Bytes of Content Length for Value Representations holding long
    > content
    >
    > * In Implicit Transfer Syntaxes, the Tag is always followed by 4 Byte of
    > length.
    >
    > There are Little Endian Syntaxes as well as Big Endian Syntaxes. There
    > may be deflated Syntax.
    >
    > Some Tags may hold sequences (a "mini-Dataset" of other Tags) with
    > several Items. These may have undefined length, so you will only stay in
    > sync when parsing "everything".
    >
    > Can you see it is not that easy? This *is* complicated.
    >
    > To get a basic understanding, please read part 5 of the DICOM Standard
    > thoroughly. Then read related parts (in some way, all are related). It
    > is hard to get started, I agree, but an "easy way" will not do the job
    > you described safely and an conformant way.
    >
    > I do not want to discourage you, but the ambition to implement "DICOM
    > quickly" is high.
    >
    > If you really need only "some attribute's content", use a lib. Or even
    > more simplified, spawn a console dump tool available in many different
    > flavors from many different toolkits in many different license models
    > and parse their output.
    >
    > Personally, I would recommend to use a DICOM to XML dump tool (which
    > typically do not include binary payload data like pixel data or digital
    > waveforms in their output) and parse the output XML tree until you got
    > your information, this is safe and still rather easy. The tool to recall
    > right from the top of my head would be dcmtk's dicom2xml (->http://dicom.offis.de/dcmtk.php.en), but I am sure there are many others.
    >
    > Then, if you want to find out basic information about the Attributes you
    > have now parsed _correctly_ (the toolkit does the trick) without having
    > to implement Part 5 yourselves, you may take the shortcut of looking up
    > the Tag in Part 6 and the Semantics in Part 3, and you are almost done ;-)
    >
    > If you want to start digging deeply into the DICOM world, of course, you
    > may want to implement everything from the scratch. Start a parser for
    > DICOM Data sets, then add Sequence Support and so on. This is not a
    > holiday game, it will take time, nerve and motivation, but within some
    > few years, you will maybe able to provide a toolkit yourselves.
    >
    > I hope this helps, it's just my EUR 0.02
    >
    > Have a nice weekend,
    >



    Thanks for your advice, and also to Mathieu. I spent a day or two
    pondering over two of the packages and had trouble even understanding
    how to compile the darn things! So for better or worse I re-invented
    the wheel in a crude fashion. I learnt a lot about DICOM in the
    process and have a lot of respect for the format.

    Just in case anyone finds themself in the same situation I am posting
    my "solution".


    #include
    #include

    #define SEARCH_FOR_TAGS \
    while(temp[j-3]!=tag1 || temp[j-2]!=tag2 || temp[j-1]!=*((unsigned
    short*)VR)) \
    if(++j > N) { printf("Error tags not found.\n"); exit(4); }

    int main()
    {
    FILE *file;
    char *ptr=NULL;
    char *VR="XX";
    unsigned short *temp;
    size_t N,status,j,k,tag1,tag2;

    // open dicom file
    file = fopen("i364586.MRDC.1","r");
    if(file==NULL) {
    printf("File open error.\n");
    exit(1);
    }

    // obtain file size (unsigned shorts)
    fseek(file,0,SEEK_END);
    N = ftell(file) / sizeof(unsigned short);
    rewind(file);
    printf("uint16s in file %d\n",N);

    // allocate memory for dicom
    temp = (unsigned short*)malloc(sizeof(unsigned short)*N);
    if(temp==NULL) {
    printf("Memory allocation error.\n");
    exit(2);
    }

    // read in dicom as uint16
    status = fread(temp,sizeof(unsigned short),N,file);
    fclose(file);
    if(status != N) {
    printf("File read error.\n");
    exit(3);
    }

    // start counter after dicom deadspace
    j = 66;

    // echo time
    tag1 = 0x0018;
    tag2 = 0x0081;
    VR = "DS";
    SEARCH_FOR_TAGS;
    j += 1; // skip size code
    float te = atof((char*)(&temp[j]));
    printf("te %g\n",te);

    // field strength
    tag1 = 0x0018;
    tag2 = 0x0087;
    VR = "DS";
    SEARCH_FOR_TAGS;
    j += 1; // skip size code
    float field = atof((char*)(&temp[j]));
    printf("field %g\n",field);

    // slice location
    tag1 = 0x0020;
    tag2 = 0x1041;
    VR = "DS";
    SEARCH_FOR_TAGS;
    j += 1; // skip size code
    float slice = atof((char*)(&temp[j]));
    printf("slice %g\n",slice);

    // rows
    tag1 = 0x0028;
    tag2 = 0x0010;
    VR = "US";
    SEARCH_FOR_TAGS;
    j += 1; // skip size code
    size_t rows = temp[j];
    printf("rows %d\n",rows);

    // cols
    tag1 = 0x0028;
    tag2 = 0x0011;
    VR = "US";
    SEARCH_FOR_TAGS;
    j += 1; // skip size code
    size_t cols = temp[j];
    printf("cols %d\n",cols);

    // fill in the data
    tag1 = 0x7fe0;
    tag2 = 0x0010;
    VR = "OW";
    SEARCH_FOR_TAGS;
    j += 1; // skip reserved code
    size_t size = *(unsigned int*)(&temp[j]); // get size code
    printf("size = %d\n",size);
    j += 2; // skip size code
    printf("first few data points");
    for(k=0; k<10; k++) printf(" %u",temp[j+k]);
    printf("...\n");

    // clean up
    free(temp);

    return 0;
    }

  10. Re: Read a few tags

    Not to rain on your parade, but one can kill that approach right
    away with an Icon Image Sequence that includes nested tags
    that describe rows and columns for example, of the icon rather
    than the main pixel data, and which will occur later during
    your parsing cycle. Quite apart from the obvious observation
    that searching for the binary pattern of a tag may occur in
    places other than the tag itself, either by chance of because
    the tag itself is referenced as a value.

    Not to mention that you are assuming explicit VR, and assuming a
    particular byte order on your machine with the cast to an
    unsigned short.

    This overly simplistic approach is doomed to failure and makes
    pretty much every mistake anyone ever made parsing DICOM in
    just a few short lines.

    DON'T SEARCH FOR TAG PATTERNS.

    DON'T CAST BYTE ARRAYS TO PLATFORM-SPECIFIC INTEGER TYPES.

    DON'T ASSUME EXPLICIT VALUE REPRESENTATION.

    DON'T FORGET TO HANDLE NESTED SEQUENCES.

    At the very least, parse the tags sequentially as God intended.

    Sorry to be so relentlessly negative, but I can't let this stand
    as an example in a public forum without comment.

    David

    spasmous2 wrote:

    >
    > Thanks for your advice, and also to Mathieu. I spent a day or two
    > pondering over two of the packages and had trouble even understanding
    > how to compile the darn things! So for better or worse I re-invented
    > the wheel in a crude fashion. I learnt a lot about DICOM in the
    > process and have a lot of respect for the format.
    >
    > Just in case anyone finds themself in the same situation I am posting
    > my "solution".
    >
    >
    > #include
    > #include
    >
    > #define SEARCH_FOR_TAGS \
    > while(temp[j-3]!=tag1 || temp[j-2]!=tag2 || temp[j-1]!=*((unsigned
    > short*)VR)) \
    > if(++j > N) { printf("Error tags not found.\n"); exit(4); }
    >
    > int main()
    > {
    > FILE *file;
    > char *ptr=NULL;
    > char *VR="XX";
    > unsigned short *temp;
    > size_t N,status,j,k,tag1,tag2;
    >
    > // open dicom file
    > file = fopen("i364586.MRDC.1","r");
    > if(file==NULL) {
    > printf("File open error.\n");
    > exit(1);
    > }
    >
    > // obtain file size (unsigned shorts)
    > fseek(file,0,SEEK_END);
    > N = ftell(file) / sizeof(unsigned short);
    > rewind(file);
    > printf("uint16s in file %d\n",N);
    >
    > // allocate memory for dicom
    > temp = (unsigned short*)malloc(sizeof(unsigned short)*N);
    > if(temp==NULL) {
    > printf("Memory allocation error.\n");
    > exit(2);
    > }
    >
    > // read in dicom as uint16
    > status = fread(temp,sizeof(unsigned short),N,file);
    > fclose(file);
    > if(status != N) {
    > printf("File read error.\n");
    > exit(3);
    > }
    >
    > // start counter after dicom deadspace
    > j = 66;
    >
    > // echo time
    > tag1 = 0x0018;
    > tag2 = 0x0081;
    > VR = "DS";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > float te = atof((char*)(&temp[j]));
    > printf("te %g\n",te);
    >
    > // field strength
    > tag1 = 0x0018;
    > tag2 = 0x0087;
    > VR = "DS";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > float field = atof((char*)(&temp[j]));
    > printf("field %g\n",field);
    >
    > // slice location
    > tag1 = 0x0020;
    > tag2 = 0x1041;
    > VR = "DS";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > float slice = atof((char*)(&temp[j]));
    > printf("slice %g\n",slice);
    >
    > // rows
    > tag1 = 0x0028;
    > tag2 = 0x0010;
    > VR = "US";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > size_t rows = temp[j];
    > printf("rows %d\n",rows);
    >
    > // cols
    > tag1 = 0x0028;
    > tag2 = 0x0011;
    > VR = "US";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > size_t cols = temp[j];
    > printf("cols %d\n",cols);
    >
    > // fill in the data
    > tag1 = 0x7fe0;
    > tag2 = 0x0010;
    > VR = "OW";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip reserved code
    > size_t size = *(unsigned int*)(&temp[j]); // get size code
    > printf("size = %d\n",size);
    > j += 2; // skip size code
    > printf("first few data points");
    > for(k=0; k<10; k++) printf(" %u",temp[j+k]);
    > printf("...\n");
    >
    > // clean up
    > free(temp);
    >
    > return 0;
    > }


  11. Re: Read a few tags

    Bonjour,

    Hum... If only DICOM was this simple

    If all your images comes from the same source, then your code may
    indeed work. (Though I would change the "r" in the fopen for a "rb"
    ).

    However, if the images come from different sources, then you will have
    problems with Implicit VR files, with big endian file, with image
    encapsulation, and with any of the different compression scheme
    permitted in DICOM.

    So, unless your code is intended for a one shot deal where you
    already have all the images you need to work with and do not expect to
    re-use your code with any images coming from the outside world, I am
    afraid I will have to go with the general advise: use an existing
    toolkit. Believe me I know, it took me years to get most of the bugs
    out of my DICOM libraries.

    I know getting somebody else libraries to work is not easy, and it may
    not be as rewarding than writing your own, but if you want to
    eventually share your application with others, you will need to accept
    more than some of the uncompressed explicit VR little endian images...

    If you do want to keep on this track (writing your own code) , here's
    a few suggestions:

    - open your file in binary, windows will screw up the image otherwise
    - Also look for the big endian variation of your tags
    - You do not need the VR in your main test to locate the tags, so juts
    test if it is there after you located the tags to know how to read the
    tag size (the "size" is not encoded the same way in both cases)
    if the size of the image tag is "-1" you will have to deal with
    "items"...

    This should enable you to read a few more files

    A few more hundreds of lines of codes and you'll be there

    Yves

    On Wed, 21 May 2008 11:11:29 -0700 (PDT), spasmous2
    wrote:

    >
    >Thanks for your advice, and also to Mathieu. I spent a day or two
    >pondering over two of the packages and had trouble even understanding
    >how to compile the darn things! So for better or worse I re-invented
    >the wheel in a crude fashion. I learnt a lot about DICOM in the
    >process and have a lot of respect for the format.
    >
    >Just in case anyone finds themself in the same situation I am posting
    >my "solution".
    >
    >
    >#include
    >#include
    >
    >#define SEARCH_FOR_TAGS \
    > while(temp[j-3]!=tag1 || temp[j-2]!=tag2 || temp[j-1]!=*((unsigned
    >short*)VR)) \
    > if(++j > N) { printf("Error tags not found.\n"); exit(4); }
    >
    >int main()
    >{
    > FILE *file;
    > char *ptr=NULL;
    > char *VR="XX";
    > unsigned short *temp;
    > size_t N,status,j,k,tag1,tag2;
    >
    > // open dicom file
    > file = fopen("i364586.MRDC.1","r");
    > if(file==NULL) {
    > printf("File open error.\n");
    > exit(1);
    > }
    >
    > // obtain file size (unsigned shorts)
    > fseek(file,0,SEEK_END);
    > N = ftell(file) / sizeof(unsigned short);
    > rewind(file);
    > printf("uint16s in file %d\n",N);
    >
    > // allocate memory for dicom
    > temp = (unsigned short*)malloc(sizeof(unsigned short)*N);
    > if(temp==NULL) {
    > printf("Memory allocation error.\n");
    > exit(2);
    > }
    >
    > // read in dicom as uint16
    > status = fread(temp,sizeof(unsigned short),N,file);
    > fclose(file);
    > if(status != N) {
    > printf("File read error.\n");
    > exit(3);
    > }
    >
    > // start counter after dicom deadspace
    > j = 66;
    >
    > // echo time
    > tag1 = 0x0018;
    > tag2 = 0x0081;
    > VR = "DS";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > float te = atof((char*)(&temp[j]));
    > printf("te %g\n",te);
    >
    > // field strength
    > tag1 = 0x0018;
    > tag2 = 0x0087;
    > VR = "DS";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > float field = atof((char*)(&temp[j]));
    > printf("field %g\n",field);
    >
    > // slice location
    > tag1 = 0x0020;
    > tag2 = 0x1041;
    > VR = "DS";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > float slice = atof((char*)(&temp[j]));
    > printf("slice %g\n",slice);
    >
    > // rows
    > tag1 = 0x0028;
    > tag2 = 0x0010;
    > VR = "US";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > size_t rows = temp[j];
    > printf("rows %d\n",rows);
    >
    > // cols
    > tag1 = 0x0028;
    > tag2 = 0x0011;
    > VR = "US";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip size code
    > size_t cols = temp[j];
    > printf("cols %d\n",cols);
    >
    > // fill in the data
    > tag1 = 0x7fe0;
    > tag2 = 0x0010;
    > VR = "OW";
    > SEARCH_FOR_TAGS;
    > j += 1; // skip reserved code
    > size_t size = *(unsigned int*)(&temp[j]); // get size code
    > printf("size = %d\n",size);
    > j += 2; // skip size code
    > printf("first few data points");
    > for(k=0; k<10; k++) printf(" %u",temp[j+k]);
    > printf("...\n");
    >
    > // clean up
    > free(temp);
    >
    >return 0;
    >}


  12. Re: Read a few tags

    Hi I absolutely agree with both your and David's comments. I don't
    want to reproduce this work, but it was the lesser of two evils for
    me. I couldn't even compile any of the serious packages let alone
    interface them with my code. I have used packages like FFTW and other
    numerical codes in the past but the DICOM packages were beyond me

    My fault, I know. I decided it was better to learn it from 0 than
    munge about for an unknown amount of time chasing compilation errors.

  13. Re: Read a few tags

    Hi

    spasmous2 wrote:

    > Hi I absolutely agree with both your and David's comments. I don't
    > want to reproduce this work, but it was the lesser of two evils for
    > me. I couldn't even compile any of the serious packages let alone
    > interface them with my code. I have used packages like FFTW and other
    > numerical codes in the past but the DICOM packages were beyond me


    Whilst getting C++ packages to compile on different platforms
    can certainly be non-trivial, this is a lot easier with Java
    DICOM packages, in which case you just specify the jar file in
    the class path.

    E.g., with my PixelMed toolkit, just put pixelmed.jar in the
    class path and do something in your code like:

    import com.pixelmed.dicom.*;

    AttributeList list = new AttributeList();
    list.read(filename);

    double sliceLocation = Attribute.getSingleDoubleValueOrDefault(
    list,TagFromName.SliceLocation,0.0);

    double echoTime = Attribute.getSingleDoubleValueOrDefault(
    list,TagFromName.EchoTime,0.0);

    int[] acquisitionMatrix = Attribute.getIntegerValues(
    list,TagFromName.AcquisitionMatrix);

    > My fault, I know. I decided it was better to learn it from 0 than
    > munge about for an unknown amount of time chasing compilation errors.


    Perhaps so, but now you will have to "munge about" when your code
    fails on new images.

    David

    PS. Slice Location is a worrying attribute to be using; what are you
    using it for ? If it is for 3D work, then it is a bad idea to depend
    on this.


  14. Re: Read a few tags

    On May 25, 9:18 pm, spasmous2 wrote:
    > Hi I absolutely agree with both your and David's comments. I don't
    > want to reproduce this work, but it was the lesser of two evils for
    > me. I couldn't even compile any of the serious packages let alone
    > interface them with my code. I have used packages like FFTW and other
    > numerical codes in the past but the DICOM packages were beyond me


    Hi spasmous2,

    You kept on mentionning that you were not able to compile GDCM. GDCM
    is being compiler on a varitery of plateforms (linux, win32, win64,
    SunOS, MacOSX) and compilers (gcc, xlc, CC, cl) automatically every
    night. I do not mean to say this is bullet proof, but please we you
    say it could not even compile, please copy/paste the error message. I
    am watching the gdcm mailing list and you never sent a single post
    either to the mailing or me. AFAIK dcmtk people are also very
    reactive.

    Regards,
    -Mathieu

  15. Re: Read a few tags

    On May 25, 2:06*pm, Mathieu Malaterre
    wrote:
    > On May 25, 9:18 pm, spasmous2 wrote:
    >
    > > Hi I absolutely agree with both your and David's comments. I don't
    > > want to reproduce this work, but it was the lesser of two evils for
    > > me. I couldn't even compile any of the serious packages let alone
    > > interface them with my code. I have used packages like FFTW and other
    > > numerical codes in the past but the DICOM packages were beyond me

    >
    > Hi spasmous2,
    >
    > * You kept on mentionning that you were not able to compile GDCM. GDCM
    > is being compiler on a varitery of plateforms (linux, win32, win64,
    > SunOS, MacOSX) and compilers (gcc, xlc, CC, cl) automatically every
    > night. I do not mean to say this is bullet proof, but please we you
    > say it could not even compile, please copy/paste the error message. I
    > am watching the gdcm mailing list and you never sent a single post
    > either to the mailing or me. AFAIK dcmtk people are also very
    > reactive.
    >
    > Regards,
    > -Mathieu



    First of all I would salute the efforts of spasmous2: innovators come
    from disagreement. And he/she made an effort to find a simplistic
    solution: no harm in it. The first exercise proved to work, but isnt
    generic as is obvious from various comments. But perhaps he/she doesnt
    want it to be generic, perhaps this is all he needed.

    Second, I would agree that there are some very rich and generic
    toolkits around that can make dealing with the DICOM specifications
    very easy. Howmuchever resistant one may be to using them (I admit
    they look monstrous at first), many many people spend their valuable
    free time free of cost for the community, just so these complications
    can be subdued for someone with DICOM requirements. Hats off to you
    David, Mathieu, DCMTK guys, and very few others who pioneer this.

    I myself use dcmtk (from OFFIS) for DICOM functionality for my
    entirely free application for the medical imaging community. My
    application is still in infancy, but dcmtk for sure saved me a lottttt
    of time I would have spent dealing with the specifications. Here it is
    if anyone is interested:

    http://groups.google.com/group/medic...4cc4ca74?hl=en

    Good luck spasmous2!!

+ Reply to Thread