2010-02-19 3 views
5

Bevor ich Win32 verwendet habe, habe ich FreeImage verwendet, um Bitmaps mit einer Bittiefe von mehr als 8 Bit zu laden und zu speichern. Das ist jedes Bild, mit dem ich arbeite, seit ich medizinische Bildgebung betreibe, und bevor irgendjemand etwas sagt, ja, ich und meine Kunden haben viel Geld für kontrastreiche Monitore mit hoher Helligkeit und 11 oder 12 Bit Dynamik ausgegeben . In der Tat, wenn Sie neugierig sind, requirements by the ACR for running mammography in einem Monitor mit mindestens 10 Bit Dynamikbereich.Wie kann ich ein 16-Bit-Bild in .net x64 speichern/laden?

Ich habe gerade auf x64 für die Speicher-Overheads und um alle meine Entwicklung auf eine Plattform und Compiling-Modus zu bekommen. Ich möchte lieber nicht zu win32 zurückkehren, und meine Kunden sind direkt bei mir (und erzwingen wirklich den Wechsel). FreeImage kompiliert nicht in 64-Bit-Fenstern; Es hat eine _asm-Direktive im Code, die der Compiler nicht verarbeiten kann.

Ich dachte, ich würde versuchen, die native .NET-Unterstützung in den Microsoft-Klassen. Lange Rede, kurzer Sinn: Sie funktionieren nicht und scheitern mit sehr eingeschränkten Fehlermeldungen. Ich vermute, dass Microsoft die Format16bppGrayScale-Klasse immer noch nicht unterstützt.

Vielleicht gibt es ein Problem in meinem Code. Hier ist mein Code für das Schreiben:

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

Dieser Code stürzt das Programm mit

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

Additional information: A generic error occurred in GDI+. 

interessant, vor allem, da ich nie dieses Bild auf dem Bildschirm wie folgt zeichnen möchten (auch wenn es schön wäre!) , möchte aber nur die Funktion zum Speichern/Laden verwenden. Das Bild bekommt auf der Platte geschrieben (obwohl das Programm stürzt ab), und der folgende Lesecode stürzt das Programm auch:

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 

Dieser Code stürzt das Programm mit dem Fehler:

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

Additional information: Parameter is not valid. 

Diese Ergebnisse sagen Sie mir, dass Microsoft den Format16bppGrayScale-Teil der PixelFormat-Enumeration noch nicht behoben hat. Das ist eine Schande.

Was kann ich verwenden, um 16-Bit-Graustufenbilder auf x64 mit .NET zu laden und zu speichern?

(EDIT:. Ich sollte hinzufügen, dass, während ich DICOM-Bilder speichern Sie können, ich Versuche an Nicht-Patientendaten ausgeführt werden müssen, um sicherzustellen, dass die Algorithmen sind Ton und so weiter DICOM eine Reihe von UIDs und andere erfordert erforderlichen Felder, die für das, was ich brauche, übertrieben sind, ich brauche im Moment nur Bilder und keine Patientendaten.

Antwort

3

FreeImage kann zu x64 kompiliert werden. Befolgen Sie die Anweisungen here Sie können um die _asm Direktive gehen. Es gibt auch eine kompilierte 64-Bit-DLL am unteren Ende der Seite.

Die neueste Version (3.15.1) enthält dieses Update bereits. Ich habe die Quelldistribution abgeholt, um es zu versuchen (ich bin neugierig, FreeImage in meinem eigenen Projekt zu verwenden) und die x64-Plattform kompiliert sofort.

+0

Sie haben Recht - ab sofort kompiliert das freeimage-Projekt für x64. Danke für das Aufzeigen! – mmr

0

Ich beantworte Ihre Frage nicht wirklich, habe aber zuvor die ImageDraw-Komponente verwendet, die von Neodnyamic verkauft wird, und würde sie definitiv weiterempfehlen (und verwenden). Es ist nicht kostenlos, aber eine kleine Investition wert.

+0

hrm. Es sieht so aus, als ob ImageDraw GDI + verwendet, was bedeutet, dass es exakt die gleichen Fehler haben sollte wie das, was ich jetzt bekomme, oder? – mmr

+0

Laden Sie die Testversion herunter und finden Sie es heraus.Aus dem Speicher wurde die Komponente wegen der Probleme mit GDI + gekauft. – Kane

Verwandte Themen