Skip to content

Instantly share code, notes, and snippets.

@jaime-olivares
Last active December 11, 2023 17:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jaime-olivares/ee91edd02809abe62bfd899fb9be74c0 to your computer and use it in GitHub Desktop.
Save jaime-olivares/ee91edd02809abe62bfd899fb9be74c0 to your computer and use it in GitHub Desktop.
Dicom UUID-derived UID generator
// A port from javascript: https://hcintegrations.ca/2014/05/14/quick-and-dirty-javascript-dicomweb-uid-generator/
public static string NewUID_dirty()
{
var r = new System.Random();
var uid = System.Text.RegularExpressions.Regex.Replace("2.25.xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx", "x", m => (r.Next()%16).ToString() );
return System.Text.RegularExpressions.Regex.Replace(uid, "y", m => (r.Next()&3|8).ToString());
}
// Trying to strictly follow the Dicom spec: ftp://medical.nema.org/medical/dicom/2013/output/html/part05.html#sect_B.2
// More details at: ISO/IEC 9834-8 / ITU-T X.667, Section 6.3
public static string NewUID()
{
var guid = new System.Guid().ToByteArray();
var bigint = new System.Numerics.BigInteger(guid);
return "2.25." + bigint.ToString();
}
@vbaderks
Copy link

Hi Jaime,

You NewUID() method is incorrect. It should be:

public static string NewUid()
{
    var guid = Guid.NewGuid();
    return ConvertGuidToDicomUid(ref guid);
}

internal static string ConvertGuidToDicomUid(ref Guid value)
{
    // ISO/IEC 9834-8, paragraph 6.3 (referenced by DICOM PS 3.5, B.2) defines how
    // to convert a UUID to a single integer value that can be converted back into a UUID.

    // The Guid.ToByteArray Method returns the array in a strange order (see .NET docs),
    // BigInteger expects the input array in little endian order.
    // The last byte controls the sign, add an additional zero to ensure
    // the array is parsed as a positive number.
    var octets = value.ToByteArray();
    var littleEndianOrder = new byte[]
        { octets[15], octets[14], octets[13], octets[12], octets[11], octets[10], octets[9], octets[8],
            octets[6], octets[7], octets[4], octets[5], octets[0], octets[1], octets[2], octets[3], 0 };

    return "2.25." + new BigInteger(littleEndianOrder).ToString(CultureInfo.InvariantCulture);
}

As a test you can input the sample value of ISO/IEC 9834-8, paragraph 8 and wiki.ihe.net

var sampleValue = new Guid("f81d4fae-7dec-11d0-a765-00a0c91e6bf6");
string actual = ConvertGuidToDicomUid(ref sampleValue);
Assert.Equal("2.25.329800735698586629295641978511506172918", actual);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment