代码之家  ›  专栏  ›  技术社区  ›  mmr

如何在.NET x64中保存/加载16位图像?

  •  5
  • mmr  · 技术社区  · 14 年前

    以前,当我使用win32时,我使用 FreeImage 为了加载和保存位深度大于8位的位图。这就是我所使用的每一幅图像,因为我在做医学成像,在别人说之前,是的,我和我的客户花了很多钱在高亮度、高对比度显示器上,动态范围为11或12位。事实上,如果你好奇, requirements by the ACR for running mammography 包括至少10位动态范围的监视器。

    我刚切换到X64进行内存开销,并将我的所有开发放到一个平台和编译模式上。我不想回到win32,我的客户和我在一起(真的是在强迫改变)。FreeImage不在64位Windows上编译;它在代码中有一个编译器无法处理的asm指令。

    我想我应该在Microsoft类中尝试本机.NET支持。长话短说:它们不工作,并且失败的错误消息非常有限。我怀疑这是因为微软仍然不支持Format16bppgrayscale类。

    也许我的代码有问题。这是我写的代码:

    Bitmap theBitmap = new Bitmap(inImage.XSize, inImage.YSize, PixelFormat.Format16bppGrayScale);
    
    //have to go with lockbits
    Rectangle rect = new Rectangle(0, 0, theBitmap.Width, theBitmap.Height);
    System.Drawing.Imaging.BitmapData bmpData =
        theBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
        PixelFormat.Format16bppGrayScale);
    IntPtr ptr = bmpData.Scan0;
    int theByteSize = theBitmap.Width * theBitmap.Height *2;
    byte[] theByteBuffer = new byte[theByteSize];
    System.Buffer.BlockCopy(inImage.Data, 0, theByteBuffer, 0, theByteSize);
    System.Runtime.InteropServices.Marshal.Copy(theByteBuffer, 0, ptr, theByteSize);
    theBitmap.UnlockBits(bmpData);
    
    theBitmap.Save(inDirectory + "\\" + inName);
    theBitmap.Dispose();
    

    此代码使程序崩溃

    An unhandled exception of type 
     'System.Runtime.InteropServices.ExternalException' occurred in 
     System.Drawing.dll
    
    Additional information: A generic error occurred in GDI+.
    

    很有意思,尤其是因为我从来都不想把这张图片画到屏幕上(尽管这样会很好!),但只想使用保存/加载功能。映像确实会被写入磁盘(即使程序崩溃),以下读取代码也会使程序崩溃:

    Bitmap theBitmap = new Bitmap(theCompleteName, false);
    ushort[] theData = new ushort[theBitmap.Width * theBitmap.Height];
    int x, y;
    
    switch (theBitmap.PixelFormat)
    {
        case PixelFormat.Format16bppGrayScale:
            //have to go with lockbits
            {           
                Rectangle rect = new Rectangle(0, 0, theBitmap.Width, theBitmap.Height);
                System.Drawing.Imaging.BitmapData bmpData = 
                    theBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly,
                    PixelFormat.Format16bppGrayScale);
                IntPtr ptr = bmpData.Scan0;//scanline approach left over from FreeImage
    
                for (y = 0; y < theBitmap.Height; ++y){
                    byte[] scanline = new byte[theBitmap.Width*2];
                    System.Runtime.InteropServices.Marshal.Copy(ptr, scanline, y * theBitmap.Width * 2, theBitmap.Width * 2);
                    System.Buffer.BlockCopy(scanline, 0, theData, y * theBitmap.Width * 2, theBitmap.Width * 2);
                }
                theBitmap.UnlockBits(bmpData);
            }
            break;
        //for colors, just take the red and call it a day
    
    
        case PixelFormat.Format24bppRgb:
        case PixelFormat.Format32bppArgb://really stupid reading code, always works
            for (y = 0; y < theBitmap.Height; ++y) {
                for (x = 0; x < theBitmap.Width; ++x) {
                    theData[y * theBitmap.Width + x] = (byte)(theBitmap.GetPixel(x, y).R);
                }
            }
            break;
    }
    theNewImage = new ImageContainer(theData, theBitmap.Width, theBitmap.Height, inName, inAssessmentID);
    theBitmap.Dispose();//not needed, anymore
    

    此代码使程序崩溃,并出现错误:

    An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
    
    Additional information: Parameter is not valid.
    

    这些结果告诉我,Microsoft仍然没有修复pixelformat枚举的format16bppgrayscale部分。真遗憾。

    那么,我可以用什么在带有.NET的X64上加载和保存16位灰度图像呢?

    (编辑:我应该补充一点,虽然我可以保存DICOM图像,但我需要对非患者数据进行实验,以验证算法是否正确,等等。DICOM需要一组UID和其他必要的字段,这些字段对我需要的内容来说是多余的;目前我只需要图像,而不是病人数据)。

    2 回复  |  直到 13 年前
        1
  •  3
  •   Martin Gunia    13 年前

    自由图像 可以 编译为x64。按照说明操作 here 你可以绕过 _asm 指令。页面底部还有一个已编译的64位DLL。

    最新版本(3.15.1)已包含此修复程序。我选择了源代码发行版进行尝试(我很好奇在自己的项目中使用freeimage),X64平台马上就可以编译了。

        2
  •  0
  •   Kane    14 年前

    我不是真的回答你的问题,但以前用过 Neodnyamic 并且肯定会再次推荐(和使用)它。这不是免费的,但值得一小笔投资。

    推荐文章