简体   繁体   中英

Fo-Dicom Window Change is slow

I am using the following render code. This is a slightly modified code because, in the actual code, I am getting all the files from the FTP server. CurrentWindowCenter and CurrentWindowWidth hold the current value of WL and WW. This value can be changed from the UI. I am showing the rendered WritableBitmap directly to the user using an image component inside a canvas. But the rendering of the image is very slow. Especially for images with large file sizes such as X-Ray. So, the WW and WL change is also very slow since it also uses the render function. I am not very knowledgeable about this. But is there a way to make the rendering or WW/WL change faster? Is there a way to skip the rendering of the image every time a WW/WL change happens? Any advice in the right direction is appreciated. Thanks in advance.

// assume filePath holds an actual file location. 
 var filePath = "";
 var dicomFile = new DicomFile.Open(filePath);
 var dicomImage = new DicomImage(dicomFile.DataSet);
 if (CurrentWindowCenter.HasValue && CurrentWindowWidth.HasValue)
 {
     dicomImage.WindowCenter = Convert.ToDouble(CurrentWindowCenter.Value);
     dicomImage.WindowWidth = Convert.ToDouble(CurrentWindowWidth.Value);
 }
 dicomImage.RenderImage().AsWriteableBitmap();

Environment

  • Fo-Dicom (4.0.8)
  • .NET Framework 4.8
  • WPF

My guess is that fo-dicom is not really intended for high performance and more for compatibility. For best performance you should probably use the GPU via DirectX, OpenCL or similar. Second best should be some tightly optimized SIMD code, probably using c++.

But there might be some improvements to be had using just c#. From the looks of it fo-dicom creates a new image, copies pixels to this image, and then creates a writeableBitmap and does another copy. These step will take some extra time.

My code for copying pixels and applying a lut/transfer function look like this:

public static unsafe void Mono16ToMono8(
    byte* source,
    byte* target,
    int sourceStride,
    int targetStride,
    int width,
    int height,
    byte[] lut)
{
    Parallel.For(0, height, y =>
    {
        var ySource = source + y * sourceStride;
        var yTarget = target + y * targetStride;
        var srcUshort = (ushort*)ySource;
        for (int x = 0; x < width; x++)
        {
            var sample = srcUshort[x];
            yTarget[x] = lut[sample];
        }
    });
}

And the code to do the actual update of the writeable bitmap:

public static unsafe void Update(
    this WriteableBitmap self,
    IImage source,
    byte[] lut)
{
    self.Lock();
    try
    {
        var targetPtr = (byte*)self.BackBuffer;
        fixed (byte* sourcePtr = source.Data)
        {
            if (source.PixelFormat == PixelType.Mono16)
            {
                Mono16ToMono8(
                    sourcePtr,
                    targetPtr,
                    source.Stride,
                    self.BackBufferStride,
                    source.Width,
                    source.Height,
                    lut);
            }
        }
        self.AddDirtyRect(new Int32Rect(0, 0, (int)self.Width, (int)self.Height));
    }
    finally
    {
        self.Unlock();
    }
}

This uses an internal IImage format, where source.Data is a ReadOnlySpan<byte> , but could just as well be a byte[] . I hope most of the other properties are self-explanatory. I would expect this code to be a bit faster since it avoids both allocations and some copying steps.

All of this assumes the image is in 16-bit unsigned format, that is common for dicom, but not the only format. It also assumes you can actually get a hold of a pointer to the actual pixel-buffer, and an array of the lut that maps each possible pixelvalue to a byte. It also assumes a writeablebitmap of the correct size and color space.

And as previously mentioned, if you want both high performance, and handle all possible image formats, you might need to invest time to build your own image rendering pipeline.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM