Adjusting WindowWidth And Level using ExplicitVOILUT property

Demo code to show the usage of the DicomImage property (ExplicitVOILUT) by generating and applying a LookupTable that has been calculated based on the standard DICOM windowing formula for calculating a Lookup table.

This example code assumes min and max as the range of values you need to handle in input data (anything beyond that is mapped to the first/last value) and for screen display it default to 8 bit output.  

This sample code here uses the official DICOM windowing formula and reproduces the existing window via an explicit LUT.

Code snippet:

        void createExplicitVOILUT(DicomImage image)
        {
            if (image.ExplicitVOILUT != null)
            {
                image.ExplicitVOILUT = null;
                image.VoiLUT = 1;
                return;
            }
 
            int bits = image[Keyword.BitsStored].ExistsWithValue ? (int)image[Keyword.BitsStored].Value : 8;// 8 is enough unless going to a 12 bit printer etc
            int min = -1024;
            int max = (int)(Math.Pow(2, bits) - 1);
 
            float w = image.Width;
            float l = image.Level;
            int maxoutput = (1 << bits) - 1;
 
            ushort[] LUTdata = new ushort[max - min];
            for (int i = min; i < max; i++)
            {
                // copy current windowing
                float v = ((i - l) / w + 0.5F);     // standard DICOM windowing formula - gives 0 to 1
 
                v *= maxoutput; // to go full range
                LUTdata[i - min] = (ushort)Math.Min(Math.Max(v, 0), maxoutput);
            }
 
            image.ExplicitVOILUT = new LookupTable(min, bits, true, LUTdata);
            image.VoiLUT = 1;
        }
 
 
Relevance: