3


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

dremerDT
  • 96
  • 3
  • 11

3 Answers3

4

Look at your center and width values. They may be specific for 12 or 16 bit monochrome images. That would make them significantly different than the limiting 0-255 RGB bitmaps you're using.

You'll either have to properly scale the center and width values or use the raw monochrome data.

cneller
  • 1,542
  • 1
  • 15
  • 24
  • Thanks for your answer. If I correctly understood, for the bitmap and the raw data need different values of parameters to get same result. And easier manipulate with the raw data than with bitmaps. – dremerDT Oct 09 '15 at 15:53
  • Right. The data in the DICOM header will refer to the raw data values, not a reconstructed bitmap. – cneller Oct 09 '15 at 18:56
  • It is little sadly... Because I was making a image from section of set dicom images like the MPR regime in the "Onis" program. And have one problem when user is changing window width or center I need to rerender whole set images with new parameters. I thought instead of that rerender only the section image directly. – dremerDT Oct 09 '15 at 19:37
2

I think your line

var val = (int)(((color.R - (center - 0.5)) / (width - 1) + 0.5) * 255);

is not quite correct. I think you want

var val = (int)(( (color.R - wyMin) / (width - 1) + 0.5) * 255);

You are tryng to set up a piecewise linear transformation that maps x values less than wyMin to 0, values greater that wMax to 255 and intermediate x values to intermediate values between 0 and 255.

Wilf Rosenbaum
  • 518
  • 3
  • 10
  • When using your formula, sometimes the resulting value is bigger than 255. And if that value replace by 255, unfortunately it is not expected result. I think @cneller rights. A bitmap needs different values in order to result was like with raw data. – dremerDT Oct 10 '15 at 14:24
  • Oops, I think your formula had one more mistake. Should be var val = (int)(( (color.R - wyMin) / (width - 1) ) * 255); – Wilf Rosenbaum Oct 10 '15 at 14:57
  • But yes, if the range of pixel values has changed from the original DICOM file to your input bitmap then the window center and width will have to be changed as well before they can be applied to the bitmap. – Wilf Rosenbaum Oct 10 '15 at 15:06
  • And if the original Dicom image contains rescale slope and intercept attributes (like CT images) then this would have to be accounted for when applying the window center and width to your image as well. – Wilf Rosenbaum Oct 10 '15 at 15:09
  • You will laugh, but your formula var val = (int)(( (color.R - wyMin) / (width - 1) ) * 255); returns same result like my formula var val = (int)(((color.R - (center - 0.5)) / (width - 1) + 0.5) * 255);. Anyway thanks you a lot for help, if I will succesed I will write it in this post. – dremerDT Oct 10 '15 at 15:37
  • Sorry for the confusion. Good luck. – Wilf Rosenbaum Oct 10 '15 at 15:44
0

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);
}
dremerDT
  • 96
  • 3
  • 11