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

时间:2010-02-19 06:51:57

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

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

我刚刚切换到x64以获取内存开销,并将我的所有开发都集中到一个平台和编译模式上。我宁愿不回到win32,我的客户就在我身边(并且真的强迫改变)。 FreeImage不能在64位窗口上编译;它在编译器无法处理的代码中有一个_asm指令。

我以为我会在Microsoft课程中尝试本机.NET支持。简而言之:它们不起作用,并且在错误消息非常有限的情况下失败。我怀疑是因为Microsoft仍然不支持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 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:0)

我并没有真正回答你的问题,但之前使用过Neodnyamic销售的ImageDraw组件,肯定会再推荐(并使用)它。它不是免费的,但值得一笔小额投资。