问题描述
之前,当我使用 win32 时,我使用 FreeImage 来加载和保存 bit 的位图深度大于 8 位.这是我处理的每张图像,因为我在做医学成像,在任何人说任何话之前,是的,我和我的客户已经在具有 11 位或 12 位动态范围的高亮度、高对比度显示器上花费了很多钱.事实上,如果您很好奇,ACR 对运行乳房 X 线照相术的要求包括具有至少 10 位动态范围的监视器.
Before, when I was using win32, I used FreeImage in order to load and save bitmaps of bit depth greater than 8 bits. That's every image I work with, since I'm doing medical imaging, and before anyone says anything, yes, me and my customers have spent a lot of money on high-brightness, high-contrast monitors with 11 or 12 bits of dynamic range. In fact, if you're curious, requirements by the ACR for running mammography incldue a monitor with at least 10 bits of dynamic range.
我刚刚切换到 x64 以解决内存开销,并将我的所有开发工作放到一个平台和编译模式上.我宁愿不回到 win32,而且我的客户就在我身边(并且确实迫使我做出改变).FreeImage 不能在 64 位窗口上编译;它在代码中包含一个编译器无法处理的 _asm 指令.
I just switched to x64 for the memory overheads and to get all of my development onto one platform and compiling mode. I'd rather not to back to win32, and my customers are right there with me (and really forcing the change). FreeImage does not compile on 64 bit windows; it has a _asm directive in the code that the compiler just can't handle.
我想我会在 Microsoft 类中尝试原生 .NET 支持.长话短说:它们不起作用,并且失败并显示非常有限的错误消息.我怀疑这是因为 Microsoft 仍然不支持 Format16bppGrayScale 类.
I thought I'd try the native .NET support in the Microsoft classes. Long story short: They don't work, and fail with very limited error messages. I suspect it's because Microsoft still doesn't support the Format16bppGrayScale class.
也许我的代码有问题.这是我的编写代码:
Maybe there's a problem in my code. Here's my code for writing:
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+.
有趣,特别是因为我从不想像这样将这个图像绘制到屏幕上(虽然它会很好!),但只想使用保存/加载功能.图像确实会写入磁盘(即使程序崩溃),以下读取代码也会使程序崩溃:
Interesting, especially since I never want to draw this image to the screen like this (although it would be nice!), but just want to use the save/load functionality. The image does get written to disk (even though the program crashes), and the following reading code also crashes the program:
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
此代码使程序崩溃并出现错误:
This code crashes the program with the error:
An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
Additional information: Parameter is not valid.
这些结果告诉我,微软仍然没有修复 PixelFormat 枚举的 Format16bppGrayScale 部分.太可惜了.
These results tell me that Microsoft still hasn't fixed the Format16bppGrayScale portion of the PixelFormat enumeration. That's a shame.
那么我可以使用什么来在 x64 上通过 .NET 加载和保存 16 位灰度图像?
So what can I use to load and save 16 bit grayscale images on x64 with .NET?
(我应该补充一点,虽然我可以保存 DICOM 图像,但我需要对非患者数据进行实验以验证算法是否合理,等等.DICOM 需要一组 UID 和其他必需字段这对于我需要的东西来说太过分了;我目前只需要图像,而不是患者数据).
( I should add that while I can save out DICOM images, I need to run experiments on non-patient data to verify that the algorithms are sound, and so forth. DICOM requires a set of UIDs and other required fields that are overkill for what I need; I just need images, and not patient data, at the moment).
推荐答案
FreeImage 可以 编译为 x64.按照此处的说明操作可以绕过 _asm
指令.页面底部还有一个已编译的 64 位 dll.
FreeImage can be compiled to x64. Following the instructions here you can get around the _asm
directive . There also is a compiled 64-bit dll at the bottom of the page.
最新版本 (3.15.1) 已包含此修复程序.我选择了源代码发行版进行尝试(我很好奇在我自己的项目中使用 FreeImage)并且 x64 平台立即编译正常.
The latest version (3.15.1) already contains this fix. I've picked up the source distribution to try (I'm being curious to use FreeImage in my own project) and the x64 platform compiles fine right away.
这篇关于如何在 .net x64 中保存/加载 16 位图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!