Prima, quando stavo usando win32, ho usato FreeImage per caricare e salvare bitmap di profondità di bit superiore a 8 bit. Sono tutte le immagini con cui lavoro, dal momento che sto facendo imaging medico, e prima che qualcuno dica qualcosa, sì, io e i miei clienti abbiamo speso un sacco di soldi su monitor ad alta luminosità e contrasto elevato con 11 o 12 bit di gamma dinamica . Infatti, se sei curioso, lo requirements by the ACR for running mammography include un monitor con almeno 10 bit di gamma dinamica.Come posso salvare/caricare un'immagine a 16 bit in .net x64?
Ho appena passato a x64 per i sovraccarichi di memoria e per ottenere tutto il mio sviluppo su una piattaforma e modalità di compilazione. Preferirei non tornare a vincere32, ei miei clienti sono proprio lì con me (e davvero costringendo il cambiamento). FreeImage non si compila su finestre a 64 bit; ha una direttiva _asm nel codice che il compilatore non può gestire.
Ho pensato di provare il supporto nativo .NET nelle classi Microsoft. Per farla breve: non funzionano e falliscono con messaggi di errore molto limitati. Sospetto che sia perché Microsoft ancora non supporta la classe Format16bppGrayScale.
Forse c'è un problema nel mio codice. Ecco il mio codice per la scrittura:
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();
Questo codice si blocca il programma con
An unhandled exception of type
'System.Runtime.InteropServices.ExternalException' occurred in
System.Drawing.dll
Additional information: A generic error occurred in GDI+.
interessante, soprattutto perché non ho mai voglia di disegnare questa immagine per la schermata come questa (anche se sarebbe bello!) , ma voglio solo usare la funzionalità di salvataggio/caricamento. L'immagine venga scritto su disco (anche se il programma si blocca) e il seguente codice di lettura si blocca anche il programma:
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
Questo codice si blocca il programma con l'errore:
An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
Additional information: Parameter is not valid.
Questi risultati dimmi che Microsoft non ha ancora corretto la porzione Format16bppGrayScale dell'enumerazione PixelFormat. È un peccato.
Quindi, cosa posso utilizzare per caricare e salvare immagini in scala di grigi a 16 bit su x64 con .NET?
(MODIFICA: devo aggiungere che mentre posso salvare le immagini DICOM, ho bisogno di eseguire esperimenti su dati non paziente per verificare che gli algoritmi siano validi, e così via. DICOM richiede un set di UID e altro campi che sono eccessivi per ciò di cui ho bisogno, ho solo bisogno di immagini, e non di dati del paziente, al momento).
Hai ragione-- al momento, il progetto freeimage viene compilato per x64. Grazie per segnalarlo! – mmr