Search code examples
dicomfo-dicom

Calculate window width and window center for a bitmap



I'm trying to implement a dicom viewer. For dicom file I can set window width and window center via fo-dicom framework. But sometimes I need set the parameters for a bitmap. I have found how to can do it, but it doesn't work right.

private Bitmap setWinWidthAndCenter(Bitmap bmp)
{ 
    int center = (int)vsWindowCenter.Value; 
    int width = (int)vsWindowWidth.Value;
    var wyMin = center - 0.5 - (width - 1) / 2;
    var wMax = center - 0.5 + (width - 1) / 2;
    System.Drawing.Color color;
    for (int i = 0; i < bmp.Width; i++)
    {
        for (int j = 0; j < bmp.Height; j++)
        {
            color = bmp.GetPixel(i, j);
            if (color.R <= wyMin)
                color = System.Drawing.Color.FromArgb(0, 0, 0);
            else if (color.R > wMax)
                color = System.Drawing.Color.FromArgb(255, 255, 255);
            else
            {
                var val = (int)(((color.R - (center - 0.5)) / (width - 1) + 0.5) * 255);
                color = System.Drawing.Color.FromArgb(val, val, val);
            }
            bmp.SetPixel(i, j, color);
        }
    }
    return bmp;
}

May be anyone know what is wrong.

EDIT 1:
A left image is the expected result which was received via fo-dicom library. A right image is the result after processing via my function.
enter image description here enter image description here


Solution

  • I found a solution for the problem.
    The algorithm was right, but with one thing: A bitmap has initial values of the window width and center, there is Window center: 127 and window width 255.
    All we need to do it is calculate a difference between initial values in a dicom file and values which we want to set. Then we can just add the obtained value to initial bitmap value.
    Right code shown below.

    public Bitmap setWinWidthAndCenterForBitmap(Bitmap bmp, double defaultCenter, double defaultWidth, double currentCenter, double currentWidth)
    {
        double difCenter = currentCenter - defaultCenter;
        double difWidth = currentWidth - defaultWidth;
        int WinCenter = 127 + (int)difCenter;
        int WinWidth = 255 + (int)difWidth;
        var wMin = WinCenter - 0.5 - (WinWidth - 1) / 2;
        var wMax = WinCenter - 0.5 + (WinWidth - 1) / 2;
        System.Drawing.Color color;
        for (int i = 0; i < bmp.Width; i++)
        {
            for (int j = 0; j < bmp.Height; j++)
            {
                color = bmp.GetPixel(i, j);
                color = System.Drawing.Color.FromArgb(
                    calculateColor(color.R, wMin, wMax, WinCenter, WinWidth),
                    calculateColor(color.G, wMin, wMax, WinCenter, WinWidth),
                    calculateColor(color.B, wMin, wMax, WinCenter, WinWidth));
                bmp.SetPixel(i, j, color);
            }
        }
        return bmp;
    }
    private byte calculateColor(byte c, double wMin, double wMax, double WinCenter, double WinWidth)
    {
        if (c <= wMin)
            return 0;
        else if (c > wMax)
            return 255;
        else
            return (byte)(((c - (WinCenter - 0.5)) / (WinWidth - 1) + 0.5) * 255);
    }