2010-02-19 20 views
5

Trước đó, khi tôi đang sử dụng win32, tôi đã sử dụng FreeImage để tải và lưu bitmap của độ sâu bit lớn hơn 8 bit. Đó là mọi hình ảnh tôi làm việc, vì tôi đang chụp ảnh y tế, và trước khi bất cứ ai nói bất cứ điều gì, vâng, tôi và khách hàng của tôi đã dành rất nhiều tiền cho màn hình có độ sáng cao, độ tương phản cao với 11 hoặc 12 bit phạm vi động . Trên thực tế, nếu bạn tò mò, hãy requirements by the ACR for running mammography phát một màn hình có ít nhất 10 bit phạm vi động.Làm cách nào để lưu/tải hình ảnh 16 bit trong .net x64?

Tôi vừa chuyển sang x64 cho chi phí bộ nhớ và để có được tất cả sự phát triển của tôi trên một nền tảng và chế độ biên dịch. Tôi không muốn quay lại win32, và khách hàng của tôi ở ngay đó với tôi (và thực sự buộc phải thay đổi). FreeImage không biên dịch trên cửa sổ 64 bit; nó có một chỉ thị _asm trong mã mà trình biên dịch không thể xử lý.

Tôi nghĩ mình sẽ thử hỗ trợ .NET gốc trong các lớp của Microsoft. Dài câu chuyện ngắn: Họ không làm việc, và thất bại với thông báo lỗi rất hạn chế. Tôi nghi ngờ đó là bởi vì Microsoft vẫn không hỗ trợ lớp Format16bppGrayScale.

Có thể có sự cố trong mã của tôi. Dưới đây là mã của tôi để viết:

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(); 

Mã này bị treo chương trình với

An unhandled exception of type 
'System.Runtime.InteropServices.ExternalException' occurred in 
System.Drawing.dll 

Additional information: A generic error occurred in GDI+. 

Thú vị, đặc biệt là kể từ khi tôi không bao giờ muốn vẽ hình ảnh này vào màn hình như thế này (mặc dù nó sẽ được tốt đẹp!) , nhưng chỉ muốn sử dụng chức năng lưu/tải. Những hình ảnh không được ghi vào đĩa (mặc dù chương trình bị treo), và mã đọc sau cũng bị treo chương trình:

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 

Mã này bị treo chương trình với các lỗi:

An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll 

Additional information: Parameter is not valid. 

Những kết quả cho tôi biết rằng Microsoft vẫn chưa sửa phần Format16bppGrayScale của liệt kê PixelFormat. Thật là sự xấu hổ.

Vì vậy, tôi có thể sử dụng những gì để tải và lưu ảnh màu xám 16 bit trên x64 bằng .NET?

(EDIT: Tôi nên thêm rằng trong khi tôi có thể lưu hình ảnh DICOM, tôi cần chạy thử nghiệm trên dữ liệu không phải của bệnh nhân để xác minh rằng các thuật toán là âm thanh, v.v. DICOM yêu cầu một bộ UID và các yêu cầu khác các trường quá mức cần thiết cho những gì tôi cần; Tôi chỉ cần hình ảnh và không phải dữ liệu của bệnh nhân, tại thời điểm này).

Trả lời

3

FreeImage có thể được biên dịch thành x64. Thực hiện theo các hướng dẫn here bạn có thể tham khảo chỉ thị _asm. Ngoài ra còn có một dll 64-bit biên dịch ở dưới cùng của trang.

Phiên bản mới nhất (3.15.1) đã chứa bản sửa lỗi này. Tôi đã chọn bản phân phối nguồn để thử (tôi tò mò muốn sử dụng FreeImage trong dự án của riêng mình) và nền tảng x64 biên dịch tốt ngay lập tức.

+0

Bạn đúng-- hiện tại, dự án tự do biên dịch cho x64. Cảm ơn đã chỉ ra điều đó! – mmr

0

Tôi không thực sự trả lời câu hỏi của bạn nhưng trước đây đã sử dụng thành phần ImageDraw được bán bởi Neodnyamic và chắc chắn sẽ đề xuất (và sử dụng) lại. Nó không phải là miễn phí nhưng cũng có giá trị đầu tư nhỏ.

+0

hrm. Có vẻ như ImageDraw sử dụng GDI +, có nghĩa là nó phải có cùng một lỗi chính xác như những gì tôi đang nhận được ngay bây giờ, phải không? – mmr

+0

Tải xuống bản dùng thử và tìm hiểu.Từ bộ nhớ, thành phần đã được mua vì các vấn đề với GDI +. – Kane