2010-02-19 31 views
5

之前,當我使用win32時,爲了加載和保存位深度大於8位的位圖,我使用了FreeImage。這是我工作的每一張圖片,因爲我正在做醫學成像,在任何人說什麼之前,是的,我和我的客戶花費了大量金錢在高亮度,高對比度的顯示器上,顯示器的動態範圍爲11或12位。事實上,如果你很好奇,requirements by the ACR for running mammography包含一個至少有10位動態範圍的顯示器。如何在.net x64中保存/加載16位圖像?

我剛剛切換到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. 

這些結果告訴我,微軟仍然沒有修復PixelFormat枚舉的Format16bppGrayScale部分。這太遺憾了。

那麼,我可以使用什麼來加載和保存x64與.NET的16位灰度圖像? (編輯:我應該補充說,雖然我可以省去DICOM圖像,但我需要在非患者數據上運行實驗來驗證算法是否正確,等等.DICOM需要一組UID和其他必需的這些字段對我所需要的是過度的;我現在只需要圖像,而不是耐心的數據)。

回答

3

FreeImage 可以將編譯爲x64。遵循here的說明,您可以獲得_asm指令。在頁面底部還有一個編譯的64位dll。

最新版本(3.15.1)已包含此修復程序。我已經選擇了源代碼發行版來嘗試(我正在好奇在自己的項目中使用FreeImage),並且x64平臺立即編譯完成。

+0

你是對的 - 截至目前,freeimage項目爲x64編譯。感謝您指出! – mmr

0

我沒有真正回答你的問題,但以前使用過Neodnyamic銷售的ImageDraw組件,並且肯定會推薦(並使用)它。它不是免費的,但很值得投資。

+0

hrm。它看起來像ImageDraw使用GDI +,這意味着它應該有我現在得到的完全相同的錯誤,對嗎? – mmr

+0

下載試用版並找出答案。從內存中購買組件是因爲GDI +的問題。 – Kane