【问题标题】:FO-DICOM: Resizing a window with a rendered bitmap in a C# Windows Forms application results in crashFO-DICOM:在 C# Windows 窗体应用程序中使用呈现的位图调整窗口大小会导致崩溃
【发布时间】:2023-04-05 19:34:01
【问题描述】:

我最近开始评估 fo-dicom 作为未来项目可能的 DICOM 库,所以我对它很陌生。

我构建了一个基本的 C# Windows 窗体应用程序,它只读取 DICOM 文件,将其转换为 System.Drawing.Bitmap 并显示在 PictureBox 中:

public partial class TestFoDicomForm : Form
{
    public TestFoDicomForm()
    {
        InitializeComponent();

        DicomImage di               = new DicomImage("Image_01.dcm");
        Bitmap bmp                  = di.RenderImage().AsBitmap();
        this._pbDicomImage.Image    = bmp;
    }
}

这段代码可以运行,但是如果我开始resize表单,异常来得比以后告诉要早:

System.ArgumentException:参数无效。

在 System.Drawing.Image.get_RawFormat()
在 System.Drawing.Graphics.DrawImage(图像图像,Int32 x,Int32 y,Int32 宽度,Int32 高度)
在 System.Drawing.Graphics.DrawImage(Image image, Rectangle rect)
在 System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
在 System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e,Int16 层)
在 System.Windows.Forms.Control.WmPaint(消息&m)
在 System.Windows.Forms.Control.WndProc(Message&m)
在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&m)
在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

异常实际发生在Main()

Application.Run(new TestFoDicomForm());

但我无法添加有效的 try/catch 来调查实际发生的情况。

我通过 NuGet 添加了对 fo-dicom 3.0.2 的引用(项目的目标框架是 4.6.1)。环境:Windows 10 专业版,VS 2017。

有趣的是,如果我按照上面的代码生成位图,然后将其存储,并在应用程序中读取它(不参考 DICOM)并放入图片框中,则不会发生类似的情况。这让我认为问题出在位图本身,但我无法发现,是什么。

我还有一个使用 fo-dicom.1.0.37 制作的旧测试应用程序,在调整大小时不会崩溃。

我很好奇可能是什么原因,如何消除这种影响或/以及我可能做错了什么。

(可以从http://jmp.sh/UGOg8Ai 下载测试应用程序 - 我希望)。

【问题讨论】:

    标签: c# bitmap dicom fo-dicom


    【解决方案1】:

    我的一位同事知道答案。下面的代码就是这样做的:

    public partial class TestFoDicomForm : Form
    {
        private IImage image;
    
        public TestFoDicomForm()
        {
            InitializeComponent();
    
            this.image = new DicomImage("Image_01.dcm").RenderImage();
            Bitmap bmp = image.AsBitmap();
            this.pictureBox1.Image  = bmp;
        }
    }
    

    这里的诀窍是您需要保存IImage 的实例(由于返回类型为RenderImage(),因此必须以这种形式保存为IImage)。

    【讨论】:

      【解决方案2】:

      这是 fo-dicom 中的一个已知问题,并且已经有修复,将包含在下一个版本中。 解释是,AsBitmap() 方法返回一个位图,其像素数据指向 IImage 实例拥有的内存。如果 IImage 实例释放,则 Bitmap 的指针无效。 这对于性能原因和内存消耗非常有用,因为不必复制像素数据。因此,这不是错误,而是设计的。

      新版本将有两种方法:一种表现得像当前一样具有最佳性能,另一种返回 Bitmap 并复制了自己的像素数据。

      如果您有建议或 cmets,请随时将它们添加到 github 上的问题中:

      https://github.com/fo-dicom/fo-dicom/issues/634

      【讨论】:

      • 感谢 gofal3,虽然有延迟。我已经使用了下面的解决方法。
      • 不客气。抱歉耽搁了。正如在 github 上发布的那样,更活跃的社区,如果您对 fo-dicom 有更多疑问,请访问 gitter.im/fo-dicom/fo-dicom
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      相关资源
      最近更新 更多