[Insight-developers] DICOM UID generation

Miller, James V (Research) millerjv at crd.ge.com
Thu Jan 6 10:08:21 EST 2005


Mathieu, 

My main concern with this UID generation algorithm is that 
it takes up 15 characters (16 with the trailing dot) to
add the encoding of "gdcm" into the uid. This seems like
a lot of characters and all it does is ensure that gdcm
uids are REALLY REALLY unique from the other uids that 
may be generated from that root. But the ip address and 
datestamp/timestamp should make the uid's unique enough.

You also want to transform the ip address somehow so that 
the UID cannot be easily tracked back to a particular
machine.  Having an IP address in the UID could be 
an issue with ensuring anonymonization of data.

Jim



-----Original Message-----
From: Mathieu Malaterre [mailto:mathieu.malaterre at kitware.com]
Sent: Thursday, January 06, 2005 9:51 AM
To: dclunie at dclunie.com
Cc: Insight-developers (E-mail)
Subject: Re: [Insight-developers] DICOM UID generation


David Clunie wrote:
> Hi Jim
> 
> Sending money to ANSI is a complete waste of money, since there are
> free UID roots available, and nobody cares where your root comes from
> as long as it is unique.
> 
> For other alternatives, see:
> 
> "http://www.dclunie.com/medical-image-faq/html/part8.html#UIDRegistration"
> 
> Your biggest problem though is not getting a root, it is making sure
> that every file generated by ITK anywhere no matter where and by whom
> it is installed is globally unique.
> 
> Typically this is done with something unique to the device on which it
> is installed, e.g. serial number, hostid, MAC address or similar, as
> well as any process or thread running on that device (e.g. process
> number). It is very hard to get this right in a multi-platform toolkit.
> The MAC address, process number, a date time stamp with high precision
> and a random number might be necessary. If it won't all fit into 64
> bytes, considering feeding everything (after the root) into some sort
> of cryptographic hash function.

David,

	Could you please comment on the code bellow. This is extracted from 
GDCM CVS tree.

	The code works as follow:
echo "gdcm" | od -b
0000000 147 144 143 155 012

	Then we build the UID with:

  radical (if passed in) + 147.144.143.155 + IP + time()

	Therefore even organization without radical can create unique DICOM 
images internal within their organization.

Mathieu

/**
  * \ingroup Util
  * \brief   Return the IP adress of the machine writting the DICOM image
  */
std::string Util::GetIPAddress()
{
   // This is a rip from 
http://www.codeguru.com/Cpp/I-N/internet/network/article.php/c3445/
#ifndef HOST_NAME_MAX
   // SUSv2 guarantees that `Host names are limited to 255 bytes'.
   // POSIX 1003.1-2001 guarantees that `Host names (not including the
   // terminating NUL) are limited to HOST_NAME_MAX bytes'.
#  define HOST_NAME_MAX 255
   // In this case we should maybe check the string was not truncated.
   // But I don't known how to check that...
#if defined(_MSC_VER) || defined(__BORLANDC__)
   // with WinSock DLL we need to initialise the WinSock before using 
gethostname
   WORD wVersionRequested = MAKEWORD(1,0);
   WSADATA WSAData;
   int err = WSAStartup(wVersionRequested,&WSAData);
   if (err != 0) {
       /* Tell the user that we could not find a usable */
       /* WinSock DLL.                                  */
       WSACleanup();
       return "127.0.0.1";
   }
#endif

#endif //HOST_NAME_MAX

   std::string str;
   char szHostName[HOST_NAME_MAX+1];
   int r = gethostname(szHostName, HOST_NAME_MAX);

   if( r == 0 )
   {
     // Get host adresses
     struct hostent * pHost = gethostbyname(szHostName);

     for( int i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ )
     {
       for( int j = 0; j<pHost->h_length; j++ )
       {
         if( j > 0 ) str += ".";

         str += Util::Format("%u",
             (unsigned int)((unsigned char*)pHost->h_addr_list[i])[j]);
       }
       // str now contains one local IP address

#if defined(_MSC_VER) || defined(__BORLANDC__)
   WSACleanup();
#endif

     }
   }
   // If an error occur r == -1
   // Most of the time it will return 127.0.0.1...
   return str;
}

/**
  * \ingroup Util
  * \brief Creates a new UID. As stipulate in the DICOM ref
  *        each time a DICOM image is create it should have
  *        a unique identifier (URI)
  */
std::string Util::CreateUniqueUID(const std::string& root)
{
   // The code works as follow:
   // echo "gdcm" | od -b
   // 0000000 147 144 143 155 012
   // Therefore we return
   // radical + 147.144.143.155 + IP + time()
   std::string radical = root;
   if( !root.size() ) //anything better ?
   {
     radical = "0.0."; // Is this really usefull ?
   }
   // else
   // A root was specified use it to forge our new UID:
   radical += "147.144.143.155"; // gdcm
   radical += ".";
   radical += Util::GetIPAddress();
   radical += ".";
   radical += Util::GetCurrentDate();
   radical += ".";
   radical += Util::GetCurrentTime();

   return radical;
}



_______________________________________________
Insight-developers mailing list
Insight-developers at itk.org
http://www.itk.org/mailman/listinfo/insight-developers


More information about the Insight-developers mailing list