【问题标题】:How can I save/load a 16 bit image in .net x64?如何在 .net x64 中保存/加载 16 位图像?
【发布时间】:2011-01-18 16:05:15
【问题描述】:

之前,当我使用 win32 时,我使用FreeImage 来加载和保存位深大于 8 位的位图。这是我使用的每张图像,因为我正在做医学成像,在任何人说什么之前,是的,我和我的客户已经在具有 11 位或 12 位动态范围的高亮度、高对比度显示器上花费了很多钱.事实上,如果您好奇的话,requirements by the ACR for running mammography 包括一个至少具有 10 位动态范围的显示器。

我刚刚切换到 x64 以解决内存开销,并将我的所有开发工作放到一个平台和编译模式上。我宁愿不回到 win32,而且我的客户就在我身边(并且真的迫使改变)。 FreeImage 不能在 64 位窗口上编译;它在代码中有一个编译器无法处理的 _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 部分。真可惜。

那么我可以使用什么来在 x64 上通过 .NET 加载和保存 16 位灰度图像?

(编辑:我应该补充一点,虽然我可以保存 DICOM 图像,但我需要对非患者数据进行实验以验证算法是否合理,等等。DICOM 需要一组 UID 和其他必填字段这对我需要的东西来说太过分了;我现在只需要图像,而不是患者数据)。

【问题讨论】:

    标签: .net bitmap 64-bit 16-bit image-load


    【解决方案1】:

    FreeImage 可以编译成 x64。按照here 的说明,您可以绕过_asm 指令。页面底部还有一个已编译的 64 位 dll。

    最新版本 (3.15.1) 已包含此修复程序。我已经选择了源代码分发来尝试(我很好奇在我自己的项目中使用 FreeImage)并且 x64 平台可以立即编译。

    【讨论】:

    • 你是对的——到目前为止,freeimage 项目编译为 x64。感谢您指出!
    【解决方案2】:

    我并没有真正回答您的问题,但我之前使用过 Neodnyamic 出售的 ImageDraw 组件,并且肯定会再次推荐(并使用)它。它不是免费的,但值得进行少量投资。

    【讨论】:

    • 人力资源管理。看起来 ImageDraw 使用 GDI+,这意味着它应该与我现在得到的错误完全相同,对吧?
    • 下载试用版一探究竟。由于 GDI+ 的问题,从内存中购买了该组件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2018-07-30
    • 2021-11-25
    • 1970-01-01
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多